8

在 RxSwift/RxCocoa 2.0.0- beta 3 中,我有一个 ViewModel:

let someString = Variable("")

func isValidSomeString() -> Observable<Bool>  {

    if someString.value.characters.count == 0 {
        return just(false)
    }
    return just(true)
}   

我已经将 someString 绑定到 ViewController 中的文本字段。

每当 someString (或者如果这是更好的方法,可能是文本字段)发生变化时,我希望根据 someString 是否有效启用一个按钮。

我尝试使用“Observable< Bool >”,但开始走另一条路。我可以在 ViewController 中执行此操作:

    someViewModel.someString.subscribeNext { text -> Void in

        // could just someUIButton.enabled = someViewModel.isValidSomeString(text)

    }.addDisposableTo(disposeBag)

难道没有比 isValidSomeString(text) 方法更简洁的另一种方法吗?我们已经通过 isValidLogin 取得了不错的成功,它返回了使用 combineLatest 的 Observable< Bool >。

4

2 回答 2

9

听起来像是Action在这种情况下使用的完美工具。您需要Action在 ViewModel 中创建一个,让其enabledIfobservable 成为字符串更改的结果,并将此操作连接到您的UIButton. 这样按钮将自动启用。

在您的 ViewModel 中,您需要添加以下内容:

var buttonAction: CocoaAction {
    let hasString = self.someString.map { !$0.isEmpty }
    return CocoaAction(enabledIf: hasString) {
        // do something when button tapped
        return empty()
    }
}

将 ViewController 绑定到 ViewModel 时,您将执行以下操作:

myButton.rx_action = viewModel.buttonAction
于 2015-11-30T13:26:21.797 回答
4

看起来你只需要mapsomeStringObserable<Bool>,然后将它绑定到这样rx_enabledUIButton 东西:

someViewModel.someString
             .asObservable()
             .map { (str) -> Bool in
                 return someViewModel.isValidSomeString(text)
             }
            .bindTo(someUIButton.rx_enabled)
            .addDisposableTo(disposeBag)  

但我认为如果你Variable<Bool>在你的视图模型中有这样的东西会更简单

struct ViewModel {
....
    canLogIn = Variable(false)
}

在这种情况下,您将能够rx_enabled像这样绑定它:

  let userNameValidation = loginTextField
     .rx_text
     .map({!$0.isEmpty})
     .shareReplay(1)

  let passwordValidation = passwordTextField
     .rx_text
     .map({!$0.isEmpty})
     .shareReplay(1)

  let loginEnabled = combineLatest(userNameValidation, passWordValidation) { (username, password) in
     return username && password
  }

  loginEnabled
     .bindTo(loginViewModel.canlogIn)
     .addDisposableTo(disposeBag)

  loginViewModel.canlogIn
         .bindTo(loginButton.rx_enabled)
         .addDisposableTo(disposeBag)
于 2015-12-20T19:40:38.320 回答