ReactiveCocoaを理解しようとすると、ジェネリクスやクロージャーといったSwift的には基本なところをしっかりと理解しておく必要があるみたいで、そこの知識があいまいだと正直どう動かせば良いのかさっぱりわかりません。
今回のも単に、テキストフィールドの文字列をエンターキーを押されたらViewModelに送り、ViewControllerはURLに変換されたそれをもってブラウザに表示する・・・というものです。
ただし、文字列は5文字以上ないとURLに変換しないという縛りを入れました。これは本当は文字数ではなくURLの体裁を整えているかを調べるべきなんですが、とりあえず制限をつけてみたかったので、簡単なものにしました。
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.urlField.delegate = self
self.myWebView.delegate = self
vm.action!.values.observeNext { value in
print(value.absoluteString)
self.myWebView.loadRequest(NSURLRequest(URL: value))
}
let a = self.urlField.rac_signalForControlEvents(.EditingDidEndOnExit)
.toSignalProducer()
.flatMapError{
error in return SignalProducer<AnyObject?, NoError>.empty
}
.map { value -> String in
self.urlField.text!
}
vm.urlText <~ a
cocoaAction = CocoaAction(vm.action, input: self.urlField.text!)
urlField.addTarget(cocoaAction, action: CocoaAction.selector, forControlEvents: .EditingDidEndOnExit)
}
var urlText : MutableProperty<String> = MutableProperty("")
var action : Action<String, NSURL, NSError>!
var validation: MutableProperty<Bool>!
override init() {
super.init()
validation = MutableProperty(false)
urlText.producer.startWithNext { value in
if(value.characters.count > 5){
print("true")
self.validation <~ MutableProperty(true)
}
}
action = Action(enabledIf: validation) { value in
return SignalProducer { (observer, disposable) in
print("action: " + self.urlText.value)
observer.sendNext(NSURL(string: self.urlText.value)!)
observer.sendCompleted()
}
}
}
なんかもっとスマートな書き方があると思うのですが、分からなかったので、とりあえずここまでで一旦あげます。
ソースはまたgithubにあげてます。
以下単なる蛇足
フィールドの文字列をNSURLに変換する程度ならViewController内でやった方が早いのですが、それってMVVMの考え方的にアウト?セーフ?