RxCocoa 是让 Cocoa APIs 更容易使用响应式编程的一个框架。RxCocoa 能够让我们方便地进行响应式网络请求、响应式的用户交互、绑定数据模型到 UI 控件等等。而且大多数的 UIKit 控件都有响应式扩展,它们都是通过 rx 属性进行使用。
demo下载
UILabel
用计时器的时间绑定到label上
let timer = Observable<Int>.interval(0.1, scheduler: MainScheduler.instance)
timer.map { String(format: "%0.2d:%0.2d:%0.1d", arguments: [($0 / 600) % 600, ($0 % 600 ) / 10, $0 % 10]) }
.bind(to: label.rx.text)
.disposed(by: disposeBag)
UIButton
- 按钮的点击事件
button.rx.tap
.subscribe(onNext:{ [weak self] in
self?.showMessage(text: "按钮被点击啦")
})
.disposed(by: disposeBag)
- 按钮的title和image进行绑定
//绑定title
let timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
timer.map { "\($0)" }
.bind(to: button.rx.title(for: .normal))
.disposed(by: disposeBag)
//绑定image(绑定backgroundImage也是一样的)
let timer2 = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
timer2.map{
let imageName = ( $0 % 2 == 0 ? "navBack1" : "navBack3" )
return UIImage.init(named: imageName)!
}
.bind(to: button.rx.image())
.disposed(by:disposeBag)
- 按钮的选中事件.
例子:当其中1个按钮选中的时候,将另外2个选中取消
//将按钮放入数组中,并进行强制解包
let buttons = [button1,button2,button3].map({$0!})
button1.isSelected = true
//创建一个可观察序列,它可以发送最后一次点击的按钮(也就是我们需要选中的按钮)
let selectButton = Observable.from(buttons.map({button in button.rx.tap.map{return button}}))
.merge()
//遍历按钮对selectedButton进行订阅,根据它是否是当前选中的按钮绑定isSelected属性
for btn in buttons {
selectButton.map {$0 == btn}
.bind(to: btn.rx.isSelected)
.disposed(by: disposeBag)
}
- 按钮是否可用
将UISwitch开关事件绑定和UIButton是否可使用进行绑定
switchs.rx.isOn.bind(to: button1.rx.isEnabled)
.disposed(by: disposeBag)
UISwitch
开关状态
switchs.rx.isOn.asObservable()
.subscribe(onNext:{[weak self]
print("开关状态:\($0)")
self.button2.isEnabled = $0
})
.disposed(by: disposeBag)
UITextField
- textField的值改变
textField1.rx.text.orEmpty.asObservable()
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)
- 将textField的值绑定到其他UI控件上
//文本框的变化序列
let tfInput = textField1.rx.text.orEmpty.asDriver()
.throttle(0.5)
//将内容绑定到另外一个输入框
tfInput.drive(textField2.rx.text)
.disposed(by: disposeBag)
//将内容绑定到label
tfInput.map({String(format: "当前输入了%ld个字", $0.count)})
.drive(label.rx.text)
.disposed(by: disposeBag)
//将内容绑定到button 但输入超过5个才可以点击
tfInput.map({ $0.count > 5 })
.drive(button.rx.isEnabled)
.disposed(by: disposeBag)
- 同时监听两个textField
//同事监听两个textField
Observable.combineLatest(textField1.rx.text.orEmpty,textField2.rx.text.orEmpty){
text1,text2 -> String in
return String(format: "前1个值:%@, 后1个值:%@",text1,text2)
}
.map({$0})
.bind(to: totalLabel.rx.text)
.disposed(by: disposeBag)
事件监听
通过 rx.controlEvent 可以监听输入框的各种事件,且多个事件状态可以自由组合。
- editingDidBegin:开始编辑(开始输入内容)
- editingChanged:输入内容发生改变
- editingDidEnd:结束编辑
- editingDidEndOnExit:按下 return 键结束编辑
- allEditingEvents:包含前面的所有编辑相关事件
//监听textField的回车事件
textField1.rx.controlEvent(.editingDidEndOnExit)
.subscribe(onNext:{ [weak self] in
self?.textField2.becomeFirstResponder()
})
.disposed(by: disposeBag)
//监听textField的所有事件
textField2.rx.controlEvent(.allEditingEvents)
.subscribe(onNext:{
print("正再监听所以输入事件")
})
.disposed(by: disposeBag)
UITextView
UITextView 还封装了如下几个委托回调方法:
- didBeginEditing:开始编辑
- didEndEditing:结束编辑
- didChange:编辑内容发生改变
- didChangeSelection:选中部分发生变化
textView.rx.didBeginEditing
.subscribe(onNext:{
print("开始编辑")
})
.disposed(by: disposeBag)
textView.rx.didEndEditing
.subscribe(onNext:{
print("结束编辑")
})
.disposed(by: disposeBag)
textView.rx.didChange
.subscribe(onNext:{
print("内容变了")
})
.disposed(by: disposeBag)
textView.rx.didChangeSelection
.subscribe(onNext:{
print("选择内容发生变化")
})
.disposed(by: disposeBag)