使用 RxSwift 触发的两个事件

Posted

技术标签:

【中文标题】使用 RxSwift 触发的两个事件【英文标题】:Two events fired with RxSwift 【发布时间】:2016-08-05 20:45:45 【问题描述】:

嗨,我正在学习一些 RxSwift,我不明白为什么 makeLoginRequest 被调用两次...当登录正确时,我推送到另一个控制器,但 observable 仍然通知另一个事件,所以它推送两次下一个控制器..

在 viewModel 中的代码是这样的:

let userName : Driver<String>
let password : Driver<String>

var credentials : Driver<(String, String)> 
    return Driver.combineLatest(userName, password)  usr, pwd in
        return (usr, pwd)
    


var credentialValid : Driver<Bool> 
    let usrValid = userName
        .map  $0.rangeOfString("@") != nil 
    let pwdValid = password
    .map  $0.utf8.count > 5 

    return Driver.combineLatest(usrValid, pwdValid)  usr, pwd in
        return (usr && pwd)
    


func login() -> Observable<Login?>

    return credentials.asObservable()
        .observeOn(MainScheduler.instance)
        .flatMapLatest  credential -> Observable<Login?> in
            return self.makeLoginRequest(user: credential.0, password: credential.1)
        


func makeLoginRequest(user user: String, password: String) -> Observable<Login?>

    return self.provider
        .request(APIProvider.Login(credentials: (user, password)))
        .debug()
        .mapObjectOptional(Login.self)

在控制器中

    loginModel = LoginViewModel(provider: apiProvider! as! RxMoyaProvider<APIProvider>, userName: userTextField.rx_text.asDriver(), password: passwordTextField.rx_text.asDriver())

    loginModel.credentialValid
        .driveNext  [unowned self] valid in
            self.loginButton.enabled = valid
        
        .addDisposableTo(disposeBag)

    loginButton.rx_tap
        .debug()
        .flatMap( self.loginModel.login() )
        .subscribeNext( login  in
          // handle here login data
        )
        .addDisposableTo(disposeBag)

谁能解释一下是怎么回事?

谢谢!

【问题讨论】:

【参考方案1】:

您的问题可能在于您未显示的代码:userNamepasswordprovider。此外,您包括了credentialsValid,但它没有被使用。再说一遍,也许是该方法的某些内容,以及您如何在实际代码中使用它。

附带说明,您不应该在视图控制器中使用像这样嵌套的subscribeNext。您应该使用flatMap 并仅订阅最终的Observable

看看你是否能想出一个代码示例来说明你的问题,我们可以实际运行,然后我们可以提供帮助。通过举这个例子,你可能会自己找出问题所在。

【讨论】:

我用您指出的凭据有效编辑了原始答案。什么是没有嵌套订阅Next的正确方法?问题是 makeLoginRequest 方法被调用了两次,它会推送一个视图控制器,如果执行两次它会推送两次,这是绝对错误的。 同样,您应该使用flatMap 而不是嵌套的subscribeNexts,它将替换当前的Observable,因此您只需订阅一次。您的编辑显示了您如何使用credentialValid,但这看起来不是问题。我仍然相信未知的userNamepasswordprovider 属性可能是问题所在。但同样,没有看到代码,我不能说。同样,您应该将此问题分解为可以在此处发布的简单内容。这样做你可能会找出问题所在,如果没有,我们至少可以运行它。 我知道如何在那里使用平面地图...但这不是解决方案。 您的问题过于依赖于您的整个应用程序。您可能需要分享您的项目回购才能真正得到答案。但是,这不适用于 ***。只是没有足够的信息来帮助你。

以上是关于使用 RxSwift 触发的两个事件的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift 跳过事件直到自己的序列完成

RxSwift 简单 withLatestFrom 不触发

RxSwift之订阅UITableViewCell里的按钮点击事件

带有 UITextFieldDelegate 的 RxSwift 控制事件

RxSwift 调用 bind 立即触发 vs subscribe(onNext: )

RxSwift - 在 UISearchBar 中以编程方式触发搜索