RAC7.0 在Swift项目中的基本使用
https://blog.csdn.net/aluoshiyi/article/details/80844895
2018年06月28日 16:14:41 林升起 阅读数:311
一 、集成
在Podfile文件中加入 pod 'ReactiveCocoa', '~> 7.2.0',会自动集成ReactiveCocoa,ReactiveSwift,Result三个库,导入头文件就可以使用了。
二、基本用法
2.1 用户交互
// 监听文本框输入内容
accountTextField.reactive.continuousTextValues.observeValues { (text) in
print("account\(text ?? "")")
}
// 监听按钮的点击事件
loginBtn.reactive.controlEvents(.touchUpInside).observeValues { (button) in
print("loginBtnClick")
}
2.2 过滤
// 当文本的内容长度大于3的时候,才想监听文本的内容
passwordTextField.reactive.continuousTextValues.filter { (text) -> Bool in
return text!.count > 3
}.observeValues { (text) in
print("accountfilter\(text ?? "")")
}
2.3 转换
// text的值映射成text的字符数
textField.reactive.continuousTextValues.map { (text) -> Int in
return (text?.characters.count)!
}.filter { (length) -> Bool in
return length > 5
}.observe { (length) in
print(length)
}
2.4 冷信号
func getChatArray() -> SignalProducer<Any, NoError> {
return SignalProducer<Any, NoError>.init { (observer, _) in
self.request.GET(url: Host, paras: nil, success: { (request, response) in
if let response = response {
self.dataArray = self.WebArray()
observer.send(value: response)
observer.sendCompleted()
}
}, failure: { (request, error) in
observer.sendCompleted()
})
}
}
// 创建信号,执行
loadDataAction = Action.init(execute: getChatArray)
loadDataAction?.apply().start()
// observer 监听
viewModel.loadDataAction?.events.observe({ (event) in
print(event)
})
2.5 热信号
// 热信号
let (signalA, observerA) = Signal<String, NoError>.pipe()
let (signalB, observerB) = Signal<String, NoError>.pipe()
// 联合信号
Signal.combineLatest(signalA, signalB).observeValues { (value) in
print( "收到的值\(value.0) + \(value.1)")
}
observerA.send(value: "1")
//注意:如果加这个就是,发了一次信号就不能再发了
observerA.sendCompleted()
observerB.send(value: "2")
observerB.sendCompleted()
三、总结
知识点:区别冷信号和热信号
Swift中,SignalProducer 对应 RACSignal 为冷信号, Signal 对应的 RACSubject 为热信号。
1.冷信号模式,是被动的,需要有人订阅才开启热信号,热信号是主动的,就算没有订阅者也会即刻推送
热信号可以有多个订阅者,一对多;冷信号只能一对一,当有新的订阅者,信号是重新完整发送的
形象的说:热信号像是直播,冷信号像是点播
2..冷信号个人用来进行网络请求,热信号进行类似代理或者通知的数据传递模式,这样就可以简单的理解为,RAC其实就是把apple的一套 delegate,Notification,KVO等一系列方法综合起来了,用起来更舒服罢了。
RAC,ReactiveSwift
1.创建信号
// 1.通过信号发生器创建(冷信号)
let producer = SignalProducer<String, NoError>.init { (observer, _) in
print("新的订阅,启动操作")
observer.send(value: "Hello")
observer.send(value: "World")
}
let subscriber1 = Observer<String, NoError>(value: { print("观察者1接收到值 \($0)") })
let subscriber2 = Observer<String, NoError>(value: { print("观察者2接收到值 \($0)") })
print("观察者1订阅信号发生器")
producer.start(subscriber1)
print("观察者2订阅信号发生器")
producer.start(subscriber2)
//注意:发生器将再次启动工作
// 2.通过管道创建(热信号)
let (signalA, observerA) = Signal<String, NoError>.pipe()
let (signalB, observerB) = Signal<String, NoError>.pipe()
Signal.combineLatest(signalA, signalB).observeValues { (value) in
print( "收到的值\(value.0) + \(value.1)")
}
observerA.send(value: "1")
//注意:如果加这个就是,发了一次信号就不能再发了
observerA.sendCompleted()
observerB.send(value: "2")
observerB.sendCompleted()
//3.创建空信号
let emptySignal = Signal<Any, NoError>.empty
emptySignal.observe { (value) in
}
2.基本控件用法
//MARK:通知
private func noti() {
NotificationCenter.default.reactive.notifications(forName: Notification.Name(rawValue: "UIKeyboardWillShowNotification"), object: nil).observeValues { (value) in
}
NotificationCenter.default.post(name: Notification.Name(rawValue: "name"), object: self)
}
//MARK:KVO
private func kvoWithRac() {
view.reactive.values(forKeyPath: "bounds").start { [weak self](rect) in
print(self?.view ?? "")
print(rect)
}
}
//MARK:按钮点击
private func btnWithRAC() {
//1.点击
btn.tag = 10
btn.isEnabled = true
btn.reactive.controlEvents(.touchUpInside).observeValues { (btn) in
print("点击了按钮,颜色\(btn.tag)")
}
}
//textField
textField.reactive.continuousTextValues.observeValues { (value) in
}
3.过滤 filter
//filter作用:过滤 当text>5才会输出
textField.reactive.continuousTextValues.filter { (text) -> Bool in
return (text?.characters.count)! > 5
}.observe({
text in
print(text)
})
4.转换 map
//每一次map接收到的Value事件,它就会运行closure,以closure的返回值作为Value事件发送出去。上面的代码中,我们的text的值映射成text的字符数
textField.reactive.continuousTextValues.map { (text) -> Int in
return (text?.characters.count)!
}.filter { (length) -> Bool in
return length > 5
}.observe { (length) in
print(length)
}
//(改变属性)使用map与observeValues结合改变属性
textField.reactive.continuousTextValues
.map { (text) -> Int in
return (text?.characters.count)!
}
.map { (length) -> UIColor in
return length > 5 ? UIColor.red : UIColor.yellow
}
.observeValues { (backgroundColor) in
self.textField.backgroundColor = backgroundColor
}
5.两个信号结合使用 <~
//1.
let nameSign = textField.reactive.continuousTextValues.map { (text) -> Int in
return (text?.characters.count)!
}
let passSign = passwordtextField.reactive.continuousTextValues.map { (text) -> Int in
return (text?.characters.count)!
}
btn.reactive.isEnabled <~ Signal.combineLatest(nameSign, passSign).map({(namelength : Int, passlength : Int) -> Bool in
return namelength >= 1 && passlength > 6
})
//2.
Signal.combineLatest(nameSign,passSign).observeValues { (namelength : Int, passlength : Int) in
}
6.Scheduler(调度器)延时加载
// 主线程上延时0.3秒调用
QueueScheduler.main.schedule(after: Date.init(timeIntervalSinceNow: 0.3)) {
print("主线程调用")
}
QueueScheduler.init().schedule(after: Date.init(timeIntervalSinceNow: 0.3)){
print("子线程调用")
}
7.迭代器
// 数组的迭代器
let array:[String] = ["name","name2"]
var arrayIterator = array.makeIterator()
while let temp = arrayIterator.next() {
print(temp)
}
// swift 系统自带的遍历
array.forEach { (value) in
print(value)
}
// 字典的迭代器
let dict:[String: String] = ["key":"name", "key1":"name1"]
var dictIterator = dict.makeIterator()
while let temp = dictIterator.next() {
print(temp)
}
// swift 系统自带的遍历
dict.forEach { (key, value) in
print("\(key) + \(value)")
}
8.信号联合
func testZip() {
let (signalA, observerA) = Signal<Any, NoError>.pipe()
let (signalB, observerB) = Signal<String, NoError>.pipe()
Signal.zip(signalA, signalB).observeValues { (value) in
print(value)
}
signalA.zip(with: signalB).observeValues { (value) in
}
observerA.send(value: "1")
observerA.sendCompleted()
observerB.send(value: "2")
observerB.sendCompleted()
}
9.代替delegate
1.
import ReactiveCocoa
import ReactiveSwift
import Result
2.let (signalTap , observerTap) = Signal<Any, NoError>.pipe()
observerTap.send(value: tap)
自定义个view
class LyContentView: UIView {
let (signalTap , observerTap) = Signal<Any, NoError>.pipe()
override init(frame: CGRect) {
super.init(frame: frame)
setUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension LyContentView {
fileprivate func setUI() {
backgroundColor = UIColor.yellow
let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapClick(_:)))
addGestureRecognizer(tap)
}
//使用RAC,替代delegate,闭包
@objc fileprivate func tapClick(_ tap : UITapGestureRecognizer) {
observerTap.send(value: tap)
}
}
3.控制器中监听
contentView.signalTap.observeValues { (value) in
print("点击了view")
}
Demo:https://github.com/zhangjie579/LyReactiveSwiftDemo