Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- MVVM
- uitableview
- UITextView
- RxCocoa
- Clean Code
- rxswift
- 리펙토링
- 스위프트
- Human interface guide
- tableView
- Refactoring
- UICollectionView
- SWIFT
- Xcode
- Observable
- ribs
- uiscrollview
- 리펙터링
- combine
- collectionview
- 리팩토링
- swift documentation
- swiftUI
- Protocol
- map
- 애니메이션
- ios
- HIG
- 클린 코드
- clean architecture
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] RxSwift로 retry 사용 방법 (네트워크 재시도, 에러처리) 본문
retry를 쓰는 케이스
- 특정 네트워크에서 request 후에 response로 error를 받은 경우, 횟수나 exponential같은 시간 정책을 정해서 retry하는 경우에 사용
- 특정 처리에서 error를 받은 경우, 몇초 있다가 몇번은 retry하는 경우 사용
- RxSwift를 사용한다고 할때, Observable 스트림에서 retry 연산자를 통해 쉽게 처리가 가능
예제에 사용할 프레임워크
데이터 준비
- 3개의 데이터를 방출한 후 error를 방출하는 Observable 생성
let someObservable = Observable<String>.create { observer in
observer.onNext("1")
observer.onNext("2")
observer.onNext("3")
let myError = NSError(domain: "MyError", code: 0)
observer.onError(myError)
return Disposables.create()
}
- 데이터 확인
self.someObservable
.subscribe { print($0) }
.disposed(by: self.disposeBag)
/*
next(1)
next(2)
next(3)
error(Error Domain=MyError Code=0 "(null)")
*/
연산자 retry(_:)
- 단순히 몇번 재시도할 것인지 확인
// RxSwift.swift
public func retry(_ maxAttemptCount: Int)
-> Observable<Element> {
CatchSequence(sources: Swift.repeatElement(self.asObservable(), count: maxAttemptCount))
}
- 사용방법 - 인자에 몇번 시도할것인지 값을 넣어서 사용
- 주의) 2를 넣으면 2번 시도한다는 의미 (2번재시도가 아님을 주의)
self.someObservable
.retry(2) // 에러가 발생한 경우 한 번 retry
.subscribe { print($0) }
.disposed(by: self.disposeBag)
/*
next(1)
next(2)
next(3)
next(1)
next(2)
next(3)
error(Error Domain=MyError Code=0 "(null)")
*/
연산자 retry(when:)
- error Observable을 그대로 전달받고, 리턴타입으로는 delay와 같은 TriggerObservable을 리턴받는 타입)
public func retry<TriggerObservable: ObservableType>(
when notificationHandler: @escaping (Observable<Swift.Error>) -> TriggerObservable
) -> Observable<Element> {
RetryWhenSequence(sources: InfiniteSequence(repeatedValue: self.asObservable()), notificationHandler: notificationHandler)
}
- 구현
- 횟수: errorObservable.enumerated()을 하면 몇번 시도하는지 count값을 알 수 있으므로 이 값을 사용
- 딜레이: Observable의 delay연산자를 통해 몇초후에 시도할것인지 정의가 가능
let scheduler = MainScheduler.asyncInstance
self.someObservable
.observe(on: scheduler)
.retry(
when: { errorObservable in
errorObservable.enumerated()
.flatMap { count, error -> Observable<Void> in
guard count < 3 else { throw error }
return Observable<Void>.just(())
.delay(.seconds(1), scheduler: scheduler)
}
}
)
.subscribe(
onNext: { print($0) },
onError: { print($0) },
onCompleted: { print("completed") },
onDisposed: { print("disposed") }
)
.disposed(by: self.disposeBag)
/*
1
2
3
1
2
3
1
2
3
1
2
3
Error Domain=MyError Code=0 "(null)"
disposed
*/
cf) 만약 2의 제곱으로 retry하고 싶은 경우, .delay 안의 secnods값에 count값를 이용하여 수정
.retry(
when: { errorObservable in
errorObservable.enumerated()
.flatMap { count, error -> Observable<Void> in
guard count < 3 else { throw error }
let retryDyaly = Int(pow(Double(count), 2))
return Observable<Void>.just(())
.delay(.seconds(retryDyaly), scheduler: scheduler)
}
}
)
* 전체 코드: https://github.com/JK0369/ExRetry
'iOS 응용 (swift)' 카테고리의 다른 글
Comments