2015-11-30 2 views
4

В RxSwift/RxCocoa 2.0.0- беты 3, у меня есть ViewModel с:Использование RxSwift, как включить UIButton на основе допустимого текста?

let someString = Variable("") 

func isValidSomeString() -> Observable<Bool> { 

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

Я имею SomeString связанное уже в текстовом поле в ViewController.

Всякий раз, когда изменяется someString (или, возможно, текстовое поле, если это лучший способ), я хочу, чтобы кнопка включалась на основе if someString.

Я пробовал использовать «Наблюдаемый < Bool>», но начал спускаться по другому пути. Я мог бы сделать это в ViewController:

someViewModel.someString.subscribeNext { text -> Void in 

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

    }.addDisposableTo(disposeBag) 

Не существует еще один способ, который менее многословен, чем (текст) подход isValidSomeString? У нас уже был хороший успех с isValidLogin, который возвращает Observable < Bool> который использовал combLatest.

+0

As а также используя пример выше, можно также просто вернуть self.someString.map {! $ 0.isEmpty} в isValidSomeString. В контроллере просмотра привяжите someUIButton.rx_enabled к элементу someViewModel.isValidSomeString() – finneycanhelp

ответ

7

Похоже, Action - идеальный инструмент для использования в этом случае. Вам нужно создать Action в вашей ViewModel, чтобы его наблюдаемый enabledIf был результатом изменений в строке и подключил это действие к вашему 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 
4

Похоже, вам просто нужно map ваш someString к Obserable<Bool>, а затем привязать его к rx_enabled из UIButton Что-то вроде этого:

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

, но я думаю, что это whould будет проще, если вы бы Variable<Bool> в вашем ViewModel рода

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) 
Смежные вопросы