2016-08-11 2 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 그냥 문제를보기 위해 샘플을 추가했습니다. 텍스트 필드 사용자를 입력하고 패스 한 후 로그인을 탭하면 결과에 따라 답장을받습니다. 예를 들어 잘못된 자격 증명을 작성하고 로그인을 탭하면 subscribeNext에서 결과를 얻지 만 새로 작성하려고하면 자격 증명 신호가 한 번 더 시작됩니다 .... 나는 단지 이전 신호를 취소하고 버튼 로그인이 탭되었을 때만 새로운 신호를 발사하기를 원합니다. – jerrygdm

답변

3

프로젝트를 검토했습니다. 문제는 ViewModel의 아키텍처가 아닙니다. 예를 사용하여 RxSwift repo에서 문제를 해결합니다. 참조 아래에 새 뷰 모델 : 나는 풀 요청을 생성

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) 

, 당신이 그것을 받아 전체 소스 코드를 볼 수 있습니다

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) 
    } 
} 

은 또한 당신이 로그인 뷰 컨트롤러를 변경해야합니다. 행운을 빕니다!

+0

고마워, 난 그냥 병합, 오늘 저녁에 나는 당신의 코드를 봐 :) – jerrygdm

+0

바로 내 대답을 표시하는 것을 잊지 마세요 :) – Svyatoslav

+0

@Svyatoslav 이것은 정말 도움이되었습니다. 이렇게 정교한 대답을 해주셔서 감사합니다. – Danny