2017-05-04 157 views
0

我在學習RxSwift,並且遇到登錄邏輯問題。RxSwift代碼第一次運行,第二次運行

我的代碼運行正常嗎?一次,部分第二次,註銷後。

這是從我的視圖模型:

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

謝謝,我會將它分成兩部分後,但我不確定這可能是這裏的主要問題 – 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被第二次執行,其餘的不是。 我每次都會收到令牌,但它不會從那裏開始,我不明白爲什麼...... 我認爲沒有錯誤或完成。 – silentBob

+0

發現它,它不是視圖模型邏輯的問題,問題出在我的Rx API包裝上,每次調用後訂閱都完成了,所以我收到了響應,但它並沒有結束。 感謝iWheelBuy和Daniel T.的建議,以及Daniel T.提供了簡化,更易讀的邏輯。 – silentBob