こんにちは。
現在RxSwiftの勉強をしており、テキスト入力のバリデーションをしてボタンを有効化するという流れを作っています。
ですが以下のコードを実装すると落ちてしまいます。
View
swift
1import UIKit 2import RxCocoa 3import RxSwift 4 5class AddTabViewController: UIViewController { 6 7 @IBOutlet weak var titleLable: UILabel! 8 @IBOutlet weak var itemTextField: UITextField! 9 @IBOutlet weak var detailTextField: UITextField! 10 @IBOutlet weak var tagTextField: UITextField! 11 @IBOutlet weak var memoTextView: UITextView! 12 @IBOutlet weak var addButton: UIButton! 13 14 private lazy var viewMdoel = AddTabViewModel( 15 itemLabelObservable: itemTextField.rx.text.asObservable(), 16 detailLabelObservable: detailTextField.rx.text.asObservable(), 17 tagLabelObservable: tagTextField.rx.text.asObservable(), 18 memoLabelObservable: memoTextView.rx.text.asObservable(), 19 addButtonTapped: addButton.rx.tap.asObservable(), 20 validation: Validation() 21 ) 22 23 private let disposeBag = DisposeBag() 24 25 override func viewDidLoad() { 26 super.viewDidLoad() 27 bindingViewModel() 28 } 29 30 func bindingViewModel() { 31 32 itemTextField.rx.text 33 .bind(to: viewMdoel.itemLabel) 34 .disposed(by: disposeBag) 35 36 detailTextField.rx.text 37 .bind(to: viewMdoel.detailLabel) 38 .disposed(by: disposeBag) 39 40 tagTextField.rx.text 41 .bind(to: viewMdoel.tagLabel) 42 .disposed(by: disposeBag) 43 44 memoTextView.rx.text 45 .bind(to: viewMdoel.memoLabel) 46 .disposed(by: disposeBag) 47 48 // ここで落ちているかと思われます 49 viewMdoel.isEnableButton 50 .bind(to: addButton.rx.isEnabled) 51 .disposed(by: disposeBag) 52 53 addButton.rx.tap 54 .subscribe(onNext: { _ in 55 self.viewMdoel.addItem() 56 }) 57 .disposed(by: disposeBag) 58 } 59} 60
ViewModel
swift
1 2import Foundation 3import RxSwift 4import RxCocoa 5 6final class AddTabViewModel { 7 8 let validatedItem: Observable<Bool> 9 let validatedDetail: Observable<Bool> 10 let validatedTag: Observable<Bool> 11 let isEnableButton: Observable<Bool> 12 let itemLabel = BehaviorRelay<String?>(value: "") 13 let detailLabel = BehaviorRelay<String?>(value: "") 14 let tagLabel = BehaviorRelay<String?>(value: "") 15 let memoLabel = BehaviorRelay<String?>(value: "") 16 17 init( 18 itemLabelObservable: Observable<String?>, 19 detailLabelObservable: Observable<String?>, 20 tagLabelObservable: Observable<String?>, 21 memoLabelObservable: Observable<String?>, 22 addButtonTapped: Observable<Void>, 23 validation: TextValidate 24 ) { 25 26 27 validatedItem = itemLabelObservable 28 .flatMap { (input) -> Observable<Bool> in 29 return validation 30 .validate(text: input) 31 } 32 .share() 33 34 validatedDetail = detailLabelObservable 35 .flatMap { (input) -> Observable<Bool> in 36 return validation 37 .validate(text: input) 38 } 39 .share() 40 41 validatedTag = tagLabelObservable 42 .flatMap { (input) -> Observable<Bool> in 43 return validation 44 .validate(text: input) 45 } 46 .share() 47 48 isEnableButton = Observable.combineLatest( 49 validatedItem, 50 validatedDetail, 51 validatedTag 52 ) { 53 $0 && $1 && $2 54 } 55 .share() 56 57 } 58 59 func addItem() { 60 let item = Item( 61 name: itemLabel.value!, 62 detail: detailLabel.value!, 63 tag: tagLabel.value!, 64 memo: memoLabel.value!, 65 fav: false, 66 celllNo: items.count 67 ) 68 items.append(item) 69 } 70 71} 72 73
実行したい流れは、
3つのインプットが確認できればボタンを有効かするというものなのですが、
combineLatestの部分が間違ってるのでしょうか?
.validateではBoolを返すようにしており、
inputのtextFieldの3つがtrueならば、isEnableがtrueになるという風に
イメージして書いてみたのですが、Rxにまだ不慣れのため手こずっています。
どこに不備があるのか指摘していただけないでしょうか?
一応いかにValidationのコードも記載いたします。
よろしくお願いいたします。
Validation Model
swift
1import Foundation 2import RxSwift 3 4enum TextError: Error { 5 case blank 6 case length 7} 8 9protocol TextValidate { 10 func validate(text: String?) -> Observable<Bool> 11} 12 13final class Validation: TextValidate { 14 15 func validate(text: String?) -> Observable<Bool> { 16 switch text { 17 case .none: 18 return Observable.error(TextError.blank) 19 case let text?: 20 switch text.isEmpty { 21 case true: 22 return Observable.error(TextError.blank) 23 case false: 24 return Observable.just(true) 25 } 26 } 27 } 28} 29 30extension TextError { 31 var button: Bool { 32 switch self { 33 case .blank, .length: 34 return false 35 } 36 } 37} 38 39
追記
出現しているエラーメッセージです。
Thread 1: Fatal error: Binding error: blank
回答1件
あなたの回答
tips
プレビュー