2017-11-06 7 views
0

저는 rxSwift를 처음 사용했습니다. 나는 3 개의 관측 값, checkAccount, fetchMails 및 fetchFolders를가집니다.
fetchMails 및 fetchFolders는 checkAccount 결과에 따라 달라집니다. UIButton Tap을 사용하여 fetchMails 및 fetchFolders 작업을 호출하려면 어떻게해야합니까? 그리고 checkAccount가 성공하면 fetchMails와 fetchFolders를 실행할 때마다 실행하지 않습니다. checkAccount가 실패하면 fetchMails 및 fetchFolders를 실행할 때 checkAccount를 다시 시도하고 싶습니다. 어떻게 이러한 목적을 달성 할 수 있습니까? 그리고 이건 내 코드입니다 : @Timofey Solonin의 대답에 따라rxSwift 관찰 가능한 종속성

@IBOutlet weak var btn1: UIButton! 
@IBOutlet weak var btn2: UIButton! 
var checkAccountO: Observable<Bool>? 
let bag = DisposeBag() 

let fetchO: Observable<[String]> = Observable.create { observer in 
     DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) { 
      observer.onNext(["1","2"]) 
     } 
     return Disposables.create() 
    } 

let fetchFolderO: Observable<[String]> = Observable.create { observer in 
     DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) { 
      observer.onNext(["folder1","folder2"]) 
     } 
     return Disposables.create() 
    } 
override func viewDidLoad() { 
    super.viewDidLoad() 

    fetchFolders().subscribe { (evetn) in 
     print("folders \(evetn)") 
    }.addDisposableTo(bag) 

    fetchMails().subscribe { (evetn) in 
     print("mails \(evetn)") 
    }.addDisposableTo(bag) 
} 

func checkAccount() -> Observable<Bool> { 
    if let ob = checkAccountO { 
     return ob 
    } 
    checkAccountO = Observable.create { (observer) -> Disposable in 
     print("checking...") 
     DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) { 
      let i = arc4random() % 2 
      if i == 0 { 
       print("succ") 
       observer.onNext(true) 
       observer.onCompleted() 
      }else { 
       print("failed:\(i)") 
       let err = NSError.init(domain: "err", code: 1001, userInfo: nil) 
       observer.onError(err) 
      } 
     } 
     return Disposables.create() 
    }.retry(3).shareReplay(1) 
    return checkAccountO! 
} 

func fetchMails() -> Observable<[String]> { 
    return checkAccount().flatMap({ (_) -> Observable<[String]> in 
     return self.fetchO 
    }) 
} 

func fetchFolders() -> Observable<[String]> { 
    return checkAccount().flatMap({ (_) -> Observable<[String]> in 
     return self.fetchFolderO 
    }) 
} 

,이 같은 button.rx.tap에서 flatmap하는 것이 관찰 fetchFoders 및 fetchMails을 변경할 수 있지만 여전히

func fetchMails() -> Observable<[String]> { 
    let rxtap = btn1.rx.tap 
    return rxtap.flatMap { (_) -> Observable<[String]> in 
     return self.checkAccount().flatMap({ (_) -> Observable<[String]> in 
      return self.fetchO 
     }) 
    } 

} 

func fetchFolders() -> Observable<[String]> { 
    let rxtap = btn2.rx.tap 
    return rxtap.flatMap { (_) -> Observable<[String]> in 
     return self.checkAccount().flatMap({ (_) -> Observable<[String]> in 
      return self.fetchFolderO 
     }) 
    } 
} 
retrywhen 사용하는 방법을 알 수 없습니다

답변

1

retryWhen 연산자를 사용할 수 있습니다. flatMapretryWhen에서 checkAccount까지의 오류 스트림과 checkAccount이 성공하면 작업을 다시 시도합니다.

버튼에서 스트림을 시작하려면 button.rx.tapflatMap it을 사용하십시오.

btn1.rx.tap.flatMapLatest { 
    fetchMails().retryWhen{ errors in 
     errors.flatMapLatest{ _ in 
      checkAccount().retry() //or you can use retry(n) if you want to retry checkAccount limited amount of times. 
      //fetchMails() will repeat if checkAccount() will return anything. Just keep in mind that retryWhen block is not going to be called if checkAccount() was successful. 
     } 
    } 
} 
+0

덕분에 매우 : fetchMail() 당신이 사용할 수있는 출력 오류가 발생한 경우 예를 들어

당신은 button.rx.tapcheckAcount() 여러 번에서 fetchMail()하십시오. 이제 button.rx.tap을 사용하여 fetchMails 및 fetchfolders를 호출하는 방법을 알아 냈습니다. 하지만 retrywhen을 사용하여 내 목적을 달성하기 위해 checkAccount를 만드는 방법을 모르겠습니다. checkAccount 성공시 한 번만 실행됩니다. checkaccount가 실패하면 fetchmails가 성공할 때까지 checkaccount를 먼저 시도합니다. 몇 가지 코드를 보여줄 수 있습니까? –

+0

@ bupo.jung은 업데이트 된 답변의 예를 살펴 봅니다. 문제가 해결 되었습니까? –

+0

아니요, 제가 원하는 것이 아닙니다. fetchmails가 checkaccount 결과에 의존한다는 뜻입니다. 먼저 checkaccount 버튼 성공을 탭한 다음 fetchmails를 실행하고 결과를 얻은 다음 fetchmails를 실행 한 후에 다른 탭을 누릅니다. 처음에 checkaccount 단추를 누르는 것이 실패하면 fetchmails를 실행하지 않고 오류를 표시 한 다음, 다시 버튼을 누르기 만하면 checkaccount가 계속됩니다. –