2016-08-11 89 views
3

我有一個rxswift的基本問題。 我有一個登錄屏幕,應該調用視圖模型在我的登錄方法當且僅當我點擊登錄按鈕僅在rx_tap事件上調用方法

 loginButton.rx_tap 
     .doOn({[unowned self] _ in 
      self.loginButton.enabled = false 
     }) 
     .flatMap({[unowned self] in self.loginModel.login() }) 
     .subscribeNext({ [weak self] login in 
      self?.loginButton.enabled = true 

      guard login?.result == 1 else { 
       self?.showErrorWithMessage(login!.message) 
       return; 
      } 

      // Logged in! 
     }) 
     .addDisposableTo(disposeBag) 

看起來不錯,但如果登錄失敗,因爲憑證無效,並且用戶重新輸入上的文本字段調用loginModel.login()再次發射......

內部視圖模型還有:

var credentials : Driver<(String, String)> { 
    return Driver.combineLatest(userNameDriver.distinctUntilChanged(), passwordDriver.distinctUntilChanged()) { usr, pwd in 
     return (usr, pwd) 
    } 
} 

var usrValid : Driver<Bool> { 
    get { 
     return userNameDriver 
      .throttle(0.5) 
      .filterEmpty() 
      .distinctUntilChanged() 
      .map { ($0.rangeOfString("@") != nil) || ($0.utf8.count == 0) } 
    } 
} 

var pwdValid : Driver<Bool> { 
    get { 
     return passwordDriver 
     .throttle(0.5) 
     .filterEmpty() 
     .distinctUntilChanged() 
     .map { ($0.utf8.count > 5) || ($0.utf8.count == 0) } 
    } 
} 

var usernameBorderColor : Observable<UIColor>! 
var passwordBorderColor : Observable<UIColor>! 

var credentialValid : Driver<Bool> { 
    return Driver.combineLatest(usrValid, pwdValid) { usr, pwd in 
     return (usr && pwd) 
    } 
} 

有人能幫助我嗎? 謝謝

+1

嘿!我不能重現這個錯誤,因爲它對我來說並不明顯。你可以在Github上創建簡單的項目嗎?我將克隆它,幫助您解決它並在此主題中編寫解決方案。 – Svyatoslav

+0

在這裏您可以找到該項目:https://github.com/jerrygdm/RxTap_Issue我只是添加一個示例來查看問題。如果你在textfield用戶中輸入並傳遞,並且在你點擊登錄後你有一個基於結果的回覆....例如你寫錯了憑證並點擊登錄,你會在subscribeNext中得到結果,但是如果你嘗試寫新的信號再次啓動證書....我只想取消先前的信號,並且僅在點擊按鈕登錄時才觸發新信號。 – jerrygdm

回答

3

我回顧了你的項目。問題不是你的ViewModel的一個很好的架構。我使用RxSwift repo的示例修復了一個。請參見下面的新視圖模式:

class LoginViewModel 
{ 
let validatedUsername: Driver<Bool> 
let validatedPassword: Driver<Bool> 

// Is login button enabled 
let loginEnabled: Observable<Bool> 

// Has user log in 
let loggedIn: Observable<Login> 

var usernameBorderColor : Observable<UIColor> 
var passwordBorderColor : Observable<UIColor> 

init(input: (
    userName: Driver<String>, 
    password: Driver<String>, 
    loginClick: Observable<Void> 
    ), 
    dependency: (
    RxMoyaProvider<APIProvider> 
    ) 
    ) { 

    let credentials = Driver.combineLatest(input.userName, input.password) { ($0, $1) } 

    validatedUsername = input.userName.map { $0.rangeOfString("@") != nil } 
    validatedPassword = input.password.map { $0.utf8.count > 5 } 

    usernameBorderColor = validatedUsername.asObservable() 
     .map{valid in 
      return valid ? UIColor.clearColor() : UIColor.redColor() 
    } 
    passwordBorderColor = validatedPassword.asObservable() 
     .map{valid in 
      return valid ? UIColor.clearColor() : UIColor.redColor() 
    } 

    loginEnabled = Observable.combineLatest(
     validatedUsername.asObservable(), 
     validatedPassword.asObservable() 
    ) { username, password in 
     username && 
     password 
     } 
     .distinctUntilChanged() 
     .shareReplay(1) 

    loggedIn = input.loginClick.withLatestFrom(credentials) 
     .flatMap { username, password -> Observable<Login> in 
      var resultLogin : Login 
      if username == "[email protected]" && password == "123123" { 
       resultLogin = Login(result: 1, message: "OK") 
      } 
      else { 
       resultLogin = Login(result: 0, message: "KO") 
      } 

      return Observable.create { observer in 
       observer.onNext(resultLogin) 
       observer.onCompleted() 

       return AnonymousDisposable { 

       } 
      } 
     } 
     .retry() 
     .shareReplay(1) 
    } 
} 

而且你必須改變你的登錄視圖控制器:

let viewModel = LoginViewModel(
     input: (
      userName: userTextField.rx_text.asDriver(), 
      password: pwdTextField.rx_text.asDriver(), 
      loginClick: loginButton.rx_tap.asObservable() 
     ), 
     dependency: (
      apiProvider 
     ) 
    ) 

    viewModel.loginEnabled 
     .subscribeNext { [weak self] valid in 
      self?.loginButton.enabled = valid 
      self?.loginButton.alpha = valid ? 1.0 : 0.5 
     } 
     .addDisposableTo(self.disposeBag) 

    viewModel.loggedIn 
     .subscribeNext { login in 

      print(login.message) 

      guard login.result == 1 else { 
       // Show error 
       return; 
      } 


      } 
     .addDisposableTo(disposeBag) 

我創建拉的要求,你必須接受它,看到完整的源代碼。祝你好運!

+0

非常感謝,我只是合併,今天晚上我看看你的代碼:) – jerrygdm

+0

不要忘記標記我的答案是正確的:) – Svyatoslav

+0

@Svyatoslav這真的幫了我。謝謝你這樣詳細的回答。 – Danny

相關問題