2017-04-24 26 views
0

MVVMパターンを使用していて、ユーザーがサインインボタンを押したときにのみ警告ラベルを表示しようとします。今は表示されません。なぜなら、私はユーザーアクションだけにそれらを表示する方法がわからないからです。ユーザーが編集を開始すると、対応するラベルの警告が表示されなくなります。RxSwift - ボタンが押されたときの警告ラベルの表示/非表示

import UIKit 
import RxSwift 
import RxCocoa 
class RxLoginViewController: UIViewController { 

    @IBOutlet weak var signInButton: UIButton! 
    @IBOutlet weak var phoneNumberTextField: UITextField! 
    @IBOutlet weak var passwordTextField: UITextField! 
    @IBOutlet weak var phoneWarningLabel: UILabel! 
    @IBOutlet weak var passwordWarningLabel: UILabel! 

    fileprivate var viewModel: RxLoginViewModel? 
    private let disposeBag = DisposeBag() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     viewModel = RxLoginViewModel(phoneNumber: phoneNumberTextField.rx.text.orEmpty.asDriver(), passwordText: passwordTextField.rx.text.orEmpty.asDriver()) 
     addBindsToViewModel(viewModel: viewModel!) 
     setupButtons() 
    } 

    fileprivate func addBindsToViewModel(viewModel: RxLoginViewModel) { 
     phoneNumberTextField.rx.text 
      .orEmpty 
      .asObservable() 
      .debug("phoneNumberTextField") 
      .bindTo(viewModel.phoneNumberText) 
      .addDisposableTo(disposeBag) 

     passwordTextField.rx.text 
      .orEmpty 
      .asObservable() 
      .debug("passwordTextField") 
      .bindTo(viewModel.passwordText) 
      .addDisposableTo(disposeBag) 

     viewModel.showPhoneWarning 
      .asDriver() 
      .debug("showPhoneWarning") 
      .drive(onNext: { [weak self] showWarning in 
       UIView.animate(withDuration: 0.2) { 
        self?.phoneWarningLabel.isHidden = !showWarning 
       }} 
      ) 
      .addDisposableTo(disposeBag) 

     viewModel.showPasswordWarning 
      .asDriver() 
      .debug("showPasswordWarning") 
      .drive(onNext: { [weak self] showWarning in 
       UIView.animate(withDuration: 0.2) { 
        self?.passwordWarningLabel.isHidden = !showWarning 
       } 
      }) 
      .addDisposableTo(disposeBag) 

     viewModel.credentialsValid 
      .debug("credentialsValid") 
      .drive(onNext: { [weak self] valid in 
       self?.signInButton.isEnabled = valid 
       self?.signInButton.alpha = valid ? 1 : 0.5 
      }) 
      .addDisposableTo(disposeBag) 
    } 

    private func setupButtons() { 

     signInButton.rx.tap 
      .bindTo(viewModel!.signInAction) 
      .addDisposableTo(disposeBag) 
    } 
} 

とのViewModel: はここのViewModelへの参照を扱う私のViewControllerをである

class RxLoginViewModel { 
    let dataManager = DataManager.sharedInstance() 

    private let disposeBag = DisposeBag() 

    //MARK: - Model proprties 
    var phoneNumberText = Variable<String>("") 
    var passwordText = Variable<String>("") 
    var signInAction: Variable<Void> = Variable<Void>() 

    var showPhoneWarning = Variable(false) 
    var showPasswordWarning = Variable(false) 
    var credentialsValid: Driver<Bool> 
    var canLogIn = Variable(false) 

    init(phoneNumber: Driver<String>, passwordText: Driver<String>) { 

     let phoneValid = phoneNumber 
      .distinctUntilChanged() 
      .throttle(0.3) 
      .map { ($0 =~ RegEx.phone) } 

     let passwordValid = passwordText 
      .distinctUntilChanged() 
      .throttle(0.3) 
      .map { ($0.utf8.count > 5) } 

     credentialsValid = Driver.combineLatest(phoneValid, passwordValid) { $0 && $1 } 
     phoneNumber.debug("phone number driver") 
      .drive(onNext: {_ in self.showPhoneWarning.value = false }) 
      .addDisposableTo(disposeBag) 
     phoneNumber.debug("password driver") 
      .drive(onNext: {_ in self.showPasswordWarning.value = false }) 
      .addDisposableTo(disposeBag) 

     credentialsValid.asObservable() 
      .bindTo(canLogIn) 
      .addDisposableTo(disposeBag) 

     // actions handler 
     signInAction 
      .asObservable() 
      .debug("signInAction") 
      .do(onNext: { _ in 
       // show warning for any invalid textfield 
       // filter both valid fields 
      }) 
      // sent url request 
      .subscribe(onNext: { status in 

        self.dataManager.login(withPhone: self.phoneNumberText.value, email: "", password: self.passwordText.value, success: { (result) in 
        if let response = result as? [String : Any], response["aboutMe"] == nil { 
         self.dataManager.currentUser().userId = response["id"] as? NSNumber 
//      self.dataManager.update(.fillProfile) 
        } 
       }, failure: { (error) in 
//     print(error.localizedDescription) 

       }) 
      }) 
      .addDisposableTo(disposeBag) 
} 

私は何をどのように私のViewModelの両方の有効なフィールドをフィルタリングするには、無効なテキストフィールドの警告とを示すようにすればよいですか?

答えて

1

私は私の見解モデルあなたが行うのと同じ方法で行いませんが、うまくいけば、これはあなたを助けるでしょう...

ここで重要なのはshowPhoneWarning、観察に影響を与えることができ、すべてを概説することです。

たとえば、phoneNumberTextが無効である場合に、signInActionが入力された場合、observableをtrueにする必要があります。

はのは、変数としてその表現してみましょう:

let invalidPhoneNumberOnTap = source.phoneNumberText 
    .map { $0.isValidPhoneNumber == false } 
    .sample(source.signInAction) 

あなたはまたphoneNumberTextは、新しい要素を発射した場合、観察が偽発するようにしたいです。

let hideWarning = source.phoneNumberText.map { _ in false } 

これらの2つをマージするだけで済みます。また、警告が早期に表示されないように、最初にfalseで始まることを確認してください。

showPhoneWarning = Observable.of(invalidPhoneNumberOnTap, hideWarning) 
    .merge() 
    .startWith(false) 

showEmailWarningの処理方法とほぼ同じです。

関連する問題