2017-05-04 3 views
0

RxSwiftを学習していて、ログインロジックに問題が発生しました。RxSwiftコードが最初に2回目が部分的に実行される

私のコードは正常に実行されますか?ログアウト後、1回、部分的に2回目です。

これは私のviewmodelからである:それは初めての作品

func transform(input: Input) -> Output { 
    let user = fetchUser(loginAction: input.loginAction, domain: input.domain, 
          username: input.username, password: input.password) 

    return Output(user: user, error: errorTracker.asDriver()) 
} 

func fetchUser(loginAction: Driver<Void>, domain: Driver<String>, email: Driver<String>, password: Driver<String>)->Driver<User>{ 
    let credentials = Driver.combineLatest(domain, email, password) { 
     $0 
    } 


    return loginAction.withLatestFrom(credentials) 
     .flatMapLatest { [unowned self] (domain, username, password) in 
      return self.useCase.login(params: ["domain": domain, "username": username, "password": password]) 
       .trackActivity(self.activityIndicator) 
       .trackError(self.errorTracker) 
       .asDriverOnErrorJustComplete() 
       .map { [unowned self] in 
        if let token = $0.token { 
         return self.decodeUserId(token: token) 
        } 
        return "" 
       } 
       .flatMapLatest { [unowned self] userId in 
        return self.useCase.getUser(params: ["userId": userId]) 
         .trackActivity(self.activityIndicator) 
         .trackError(self.errorTracker) 
         .asDriverOnErrorJustComplete() 
      } 
    } 
} 
    struct Input { 
    let loginAction: Driver<Void> 
    let tenant: Driver<String> 
    let email: Driver<String> 
    let password: Driver<String> 
} 

struct Output { 
    let user: Driver<User> 
    let error: Driver<Error> 
} 

、ログインがマップの一部では、トークン文字列が含まれているオブジェクトを取得し、そのユーザーIDを取得するには、デコード、およびgetUserメソッドは、idでユーザーをフェッチします。

ビューコントローラでは、私は、この結合法います

func bindViewModel() { 
    let domainChange = domainField.rx.text.orEmpty.asDriver() 
    let usernameChange = usernameField.rx.text.orEmpty.asDriver() 
    let passwordChange = passwordField.rx.text.orEmpty.asDriver() 
    let input = LoginViewModel.Input(loginAction: loginButton.rx.tap.asDriver(), 
            domain: domainChange, 
            username: usernameChange, 
            password: passwordChange) 

    let output = viewModel.transform(input: input) 
    output.user.drive(successBinding).addDisposableTo(disposeBag) 
    output.error.drive(errorBinding).addDisposableTo(disposeBag) 
} 

successBindingとerrorBinding両方がUIBindingObserversあり、私は彼らがここでの問題はないと思います。 loginButtonをタップしようとすると、最初の部分だけが実行され、ログインメソッドが実行され、トークンが正常に取得されますが、マッピングロジックまたはユーザーフェッチロジックには移動しません。 ご協力いただければ幸いです。私は犯人はここにあると思い

+1

あなたfetchUser機能は非常に複雑です...私は私がする、小さな部分に – iWheelBuy

+0

おかげで、それを分割することをお勧めしたいです後で2つの部分に分けることができますが、私はそれがここでの主な問題であるとは確信していません – silentBob

+0

クリーナーコードは問題を理解しやすくします – iWheelBuy

答えて

1

.asDriverOnErrorJustComplete() 
.map { [unowned self] in 
    if let token = $0.token { 
     return self.decodeUserId(token: token) 
    } 
    return "" 
} 

ログインエラーやnext発光素子せずに完了した場合、マップ内のトークンの処理は何も、何もしないだろうが、チェーンを受け継がれますそれはflatMapです。あなたのコードをクリーンアップするためとして

...私はむしろこのような何かを見るでしょう:

func fetchUser(loginAction: Driver<Void>, domain: Driver<String>, email: Driver<String>, password: Driver<String>)->Driver<User>{ 
    let credentials = Driver.combineLatest(domain, email, password) 
    let latestCredentials = loginAction.withLatestFrom(credentials) 
    let loginResult = latestCredentials.flatMapLatest { [unowned self] domain, username, password in 
     self.useCase.login(params: ["domain": domain, "username": username, "password": password]) 
      .trackActivity(self.activityIndicator) 
      .trackError(self.errorTracker)     
      .asDriverOnErrorJustComplete() 
    } 
    let token = loginResult.map { result in 
     guard let token = result.token else { return "" } 
     return token 
    } 
    let userID = token.map { [unowned self] in self.decodeUserId(token: $0) } 
    return userID.flatMapLatest { userID in 
     return self.useCase.getUser(params: ["userId": userId]) 
      .trackActivity(self.activityIndicator) 
      .trackError(self.errorTracker) 
      .asDriverOnErrorJustComplete() 
    } 
} 
+0

ありがとう、昨日私はあなたのやり方と似た方法でロジックを分けましたが、問題は最初のflatMapだけが2回目に実行され、残りは実行されないということです。 毎回トークンを受け取っていますが、そこからは進まず、なぜか分かりません。 エラーや完了はないと思います。 – silentBob

+0

ビューモデルのロジックに問題はありませんでした。問題は自分のRx APIラッパーにあったので、各呼び出しの後にサブスクリプションが完了したので、応答を受信しましたが、最終的には終わらないでしょう。 iWheelBuyとDaniel T.の提案、Daniel T.の簡潔で読みやすいロジックなどのおかげで – silentBob

関連する問題