RAC類關係圖: RAC 信號源: 需要導入的頭文件: 冷信號 結果: 熱信號 文本框監聽 結果: Map映射 用於將一個事件流的值操作後的結果產生一個新的事件流。 方法一: 輸入: Hello123 結果為: 方法二: 結果為: Filter函數可以按照之前預設的條件過濾掉不滿足的值 方法一: 輸 ...
RAC類關係圖:
RAC 信號源:
需要導入的頭文件:
1 import ReactiveCocoa 2 import Result 3 import ReactiveSwift
冷信號
1 //1.冷信號 2 let producer = SignalProducer<String, NoError>.init { (observer, _) in 3 print("新的訂閱,啟動操作") 4 observer.send(value: "Hello") 5 observer.send(value: "World") 6 observer.sendCompleted() 7 } 8 9 //創建觀察者 (多個觀察者觀察會有副作用) 10 let sub1 = Signal<String, NoError>.Observer(value: { (value) in 11 print("觀察者1接受信號\(value)") 12 }) 13 14 let sub2 = Signal<String, NoError>.Observer(value: { (value) in 15 print("觀察者2接受信號\(value)") 16 }) 17 //觀察者訂閱信號 18 print("觀察者1訂閱信號") 19 producer.start(sub1) 20 print("觀察者2訂閱信號") 21 producer.start(sub2)
結果:
熱信號
1 // 熱信號 (通過管道創建) 2 let (signalA, observerA) = Signal<String, NoError>.pipe() 3 let (signalB, observerB) = Signal<Int, NoError>.pipe() 4 5 Signal.combineLatest(signalA,signalB).observeValues { (value) in 6 print("兩個熱信號收到的值\(value.0) + \(value.1)") 7 } 8 //訂閱信號要在send之前 9 signalA.observeValues { (value) in 10 print("signalA : \(value)") 11 } 12 13 observerA.send(value: "sssss") 14 // observerA.sendCompleted() 15 observerB.send(value: 2) 16 // observerB.sendCompleted() 17 18 observerB.send(value: 100) 19 //不sendCompleted和sendError 熱信號一直激活 20 // observerB.sendCompleted()
結果:
文本框監聽
1 func racsTest() { 2 textField.reactive.continuousTextValues.observeValues { (text) in 3 4 print("值為:\(text ?? "")") 5 6 } 7 }
結果:
Map映射 用於將一個事件流的值操作後的結果產生一個新的事件流。
方法一:
textField.reactive.continuousTextValues.map { (text) -> Int in return (text?.count)!//!.characters.count }.observeValues { (count) in print("數值為:\(count)") }
輸入: Hello123
結果為:
方法二:
1 let (signal, observer) = Signal<String, NoError>.pipe() 2 signal.map { (string) -> Int in 3 return string.lengthOfBytes(using: .utf8) 4 }.observeValues { (length) in 5 print("長度length: \(length)") 6 } 7 8 observer.send(value: "123456") 9 10 observer.send(value: "some")
結果為:
Filter函數可以按照之前預設的條件過濾掉不滿足的值
方法一:
1 textField.reactive.continuousTextValues.filter { (text) -> Bool in 2 3 return text!.characters.count > 3 4 5 }.observeValues { (text) in 6 7 print(text ?? "") 8 9 }
輸入: 1234
結果:
1234
方法二:
1 let (signal, observer) = Signal<Int, NoError>.pipe() 2 signal.filter { (value) -> Bool in 3 return value % 2 == 0 4 }.observeValues { (value) in 5 print("\(value)能被2整除") 6 } 7 observer.send(value: 3) 8 observer.send(value: 4) 9 observer.send(value: 6) 10 observer.send(value: 7)
結果:
4能被2整除
6能被2整除
信號合併
合成後的新事件流只有在收到每個合成流的至少一個值後才會發送出去。接著就會把每個流的最新的值一起輸出。
1 // 信號合併 兩個要被訂閱combineLatest 才能被訂閱,被訂閱後,合併中其中一個sendNext都會激活訂閱 2 let (signalA, observerA) = Signal<String, NoError>.pipe() 3 let (signalB, observerB) = Signal<Array<Any> , NoError>.pipe() 4 Signal.combineLatest(signalA, signalB).observeValues { (value) in 5 print("合併的信號:\(value)") 6 } 7 8 observerA.send(value: "xxx") 9 observerA.sendCompleted() 10 observerB.send(value: ["sdsd","ddddd"]) 11 observerB.sendCompleted()
結果:
信號聯合
zip中的信號都要被訂閱才能激活,意味著如果是一個流的第N個元素,一定要等到另外一個流第N值也收到才會一起組合發出。
1 // 信號聯合 2 let (signalA, observerA) = Signal<String, NoError>.pipe() 3 let (signalB, observerB) = Signal<String, NoError>.pipe() 4 5 //兩個到需要訂閱 才激活zip 6 Signal.zip(signalA, signalB).observeValues { (value) in 7 print("zip: \(value)") 8 } 9 10 observerA.send(value: "1") 11 // observerA.sendCompleted() 12 observerB.send(value: "2") 13 // observerB.sendCompleted() 14 observerB.send(value: "cc") 15 observerA.send(value: "dd")
結果:
調度器
1 QueueScheduler.main.schedule(after: Date.init(timeIntervalSinceNow: 3)) { 2 print("主線程3秒過去了") 3 } 4 QueueScheduler.init().schedule(after: Date.init(timeIntervalSinceNow: 2)) { 5 print("子線程2秒過去了") 6 }
結果:
通知
1 // 通知 2 NotificationCenter.default.reactive.notifications(forName: Notification.Name(rawValue: "UIKeyboardWillShowNotification"), object: nil).observeValues { (notification) in 3 print("鍵盤彈起") 4 } 5 6 NotificationCenter.default.reactive.notifications(forName: Notification.Name(rawValue:"UIKeyboardWillHideNotification"), object: nil).observeValues { (notification) in 7 print("鍵盤收起") 8 }
結果:
KVO
1 let result = self.textField.reactive.producer(forKeyPath: "text") 2 result.start { (text) in 3 print("----------->\(text)"); 4 }
輸入:Hello
註意:輸一個字元,Return 一下,否則監聽不到
結果:
迭代器
1 // 迭代器 2 let array:[String] = ["name1", "name2"] 3 var arrayIterator = array.makeIterator() 4 while let temp = arrayIterator.next() { 5 print(temp) 6 } 7 8 //swift系統自帶 9 array.forEach { (value) in 10 print("系統自帶:\(value)") 11 }
結果:
on
可以通過 on來觀察signal,生成一個新的信號,即使沒有訂閱者也會被觸發。
和 observe相似,也可以只觀察你關註的某個事件。
需要提到的是 producer要started後才會觸發。
1 let signal = SignalProducer<String , NoError>.init { (obsever, _) in 2 obsever.send(value: "SignalProducer") 3 obsever.sendCompleted() 4 } 5 6 //可以通過 on來觀察signal,生成一個新的信號,即使沒有訂閱者(sp.start())也會被觸發。 7 let sp = signal.on(starting: { 8 print("開始") 9 }, started: { 10 print("結束") 11 }, event: { (event) in 12 print("Event: \(event)") 13 }, failed: { (error) in 14 print("error: \(error)") 15 }, completed: { 16 print("信號完成") 17 }, interrupted: { 18 print("信號被中斷") 19 }, terminated: { 20 print("信號結束") 21 }, disposed: { 22 print("信號清理") 23 }) { (value) in 24 print("value: \(value)") 25 } 26 27 sp.start()
結果:
reduce
reduce將事件里的值聚集後組合成一個值
1 let (signal, observer) = Signal<Int, NoError>.pipe() 2 //reduce後的是聚合的次數 3 signal.reduce(3) { (a, b) -> Int in 4 //a是相乘後的值 b是傳入值 5 print("a:\(a) b:\(b)") 6 return a * b 7 }.observeValues { (value) in 8 print("輸出的值是:\(value)") 9 } 10 11 observer.send(value: 2) 12 observer.send(value: 5) 13 observer.send(value: 4) 14 //要註意的是最後算出來的值直到輸入的流完成後才會被髮送出去。 15 observer.sendCompleted()
結果:
flatten
flatten 將一個事件流里的事件流變成一個單一的事件流。新的事件流的值按照指定的策略(FlattenStrategy)由內部的事件流的值組成。 被壓平的值按照會變成外層的流的類型。比如:一個SignalProducers里的Signal,被flatten後的類型是SignalProducers。
合併
簡單的說就是merge
按照時間順序組成,concat
則是按照裡面整個流順序組合。latest
是只記錄最近一次過來的值的那個流。
.1 Merge 策略將每個流的值立刻組合輸出。無論內部還是外層的流如果收到失敗就終止。
1 let (producerA, lettersObserver) = Signal<String, NoError>.pipe() 2 let (producerB, numbersObserver) = Signal<String, NoError>.pipe() 3 let (signal, observer) = Signal<Signal<String, NoError>, NoError>.pipe() 4 signal.flatten(.merge).observeValues { (value) in 5 print("value: \(value)") 6 } 7 observer.send(value: producerA) 8 observer.send(value:producerB) 9 observer.sendCompleted() 10 lettersObserver.send(value:"埃及") // prints "a" 11 numbersObserver.send(value:"1") // prints "1" 12 lettersObserver.send(value:"羅馬") // prints "b" 13 numbersObserver.send(value:"2") // prints "2" 14 lettersObserver.send(value:"瑞典") // prints "c" 15 numbersObserver.send(value:"3") // prints "3"
結果:
.2 Concat 策略是將內部的SignalProducer排序。外層的producer是馬上被started。隨後的producer直到前一個發送完成後才會start。一有失敗立即傳到外層。
1 let (signalA, lettersObserver) = Signal<Any, NoError>.pipe() 2 let (signalB, numberObserver) = Signal<Any, NoError>.pipe() 3 4 let (siganl, observer) = Signal<Signal<Any, NoError>, NoError>.pipe() 5 6 siganl.flatten(.concat).observeValues { (value) in 7 print("value: \(value)") 8 } 9 observer.send(value: signalA) 10 observer.send(value: signalB) 11 observer.sendCompleted() 12 13 lettersObserver.send(value: "dddd")//dddd 14 numberObserver.send(value: 33) //不列印是因為lettersObserver的發送值沒有結束,所以 44 能列印出來 15 16 lettersObserver.send(value: "sss")//sss 17 lettersObserver.send(value: "ffff")//ffff 18 lettersObserver.sendCompleted() 19 //要前一個信號執行完畢後,下一個信號才能被訂閱 20 numberObserver.send(value: 44)// 44
結果:
.3 latest只接收最新進來的那個流的值
1 let (signalA, lettersObserver) = Signal<Any, NoError>.pipe() 2 let (signalB, numberObserver) = Signal<Any, NoError>.pipe() 3 4 let (siganl, observer) = Signal<Signal<Any, NoError>, NoError>.pipe() 5 6 siganl.flatten(.latest).observeValues { (value) in 7 print("value: \(value)") 8 } 9 observer.send(value: signalA) 10 // observer.send(value: signalB) 11 12 lettersObserver.send(value: "dddd") //dddd 13 numberObserver.send(value: 33) //不列印 14 lettersObserver.send(value: "sss") //sss 15 observer.send(value: signalB) 16 //只接受最近進來的信號 17 numberObserver.send(value: 44) //44 18 lettersObserver.send(value: "ffff") // 不列印
結果:
flatMapError
捕捉一個由SignalProducer產生的失敗,然後產生一個新的SignalProducer代替。
1 let (signal, observer) = Signal<Any, NSError>.pipe() 2 let error = NSError.init(domain: "domian", code: 0, userInfo: nil) 3 signal.flatMapError { (value) -> SignalProducer<Any, NoError> in 4 return SignalProducer<Any, NoError>.init({ () -> String in 5 return "sssss" 6 }) 7 }.observeValues { (value) in 8 print(value) 9 } 10 11 observer.send(value: "無雙") 12 observer.send(value: "鷹眼") 13 observer.send(error: error)
結果:
retry
retry用於按照指定次數,在失敗時重啟SignalProducer
1 var tries = 0 2 let limit = 2 3 let error = NSError.init(domain: "