ReactiveCocoa的核心:
信號,沒錯就是信號,發(fā)了信號要干嘛干嘛,講白了就是一個事件流;
那么我們來把這件事做一個形象的比喻:
可以把信號想象成水龍頭,只不過里面不是水,
而是玻璃球(value),直徑跟水管的內(nèi)徑一樣,
這樣就能保證玻璃球是依次排列,不會出現(xiàn)并排的情況
(數(shù)據(jù)都是線性處理的,不會出現(xiàn)并發(fā)情況)。
水龍頭的開關(guān)默認(rèn)是關(guān)的,除非有了接收方(subscriber),才會打開。
這樣只要有新的玻璃球進(jìn)來,就會自動傳送給接收方。
可以在水龍頭上加一個過濾嘴(filter),不符合的不讓通過,
也可以加一個改動裝置,把球改變成符合自己的需求(map)。
也可以把多個水龍頭合并成一個新的水龍頭(combineLatest:reduce:),
這樣只要其中的一個水龍頭有玻璃球出來,
這個新合并的水龍頭就會得到這個球。
需要說明的是因為RAC使用大量的block,請避免循環(huán)引用
例如:
[RACObserve(self,username) subscribeNext:^(NSString *newName){
NSLog(@"Name changed to %@",newName);
}];
RACObserve使用kvo來監(jiān)聽username的變化,只要有變化就會執(zhí)行block。
但不是所有的property都可以被RACObserve,該property必須支持KVO,比如NSURLCache的currentDiskUsage就不能被RACObserve。
Signal和Subscriber
Signal獲取到數(shù)據(jù)后,會調(diào)用Subscriber的sendNext,
sendComplete, sendError方法來傳送數(shù)據(jù)給Subscriber,Subscriber自然也有方法來獲取傳過來的數(shù)據(jù),如:
[signal subscribeNext:error:completed]。這樣只要沒有sendComplete和sendError,
新的值就會通過sendNext源源不斷地傳送過來.
ReactiveCocoa signal(RACSignal)
發(fā)送事件流給它的subscriber。
目前共有三種類型的事件:
next、__error__、completed。
一個signal在因error終止或者完成前,可以發(fā)送任意數(shù)量的next事件.
RACSignal有很多方法可以來訂閱不同的事件類型。
每個方法都需要至少一個block,當(dāng)事件發(fā)生時就會執(zhí)行block中的邏輯。
ReactiveCocoa 框架使用 category 來為很多基本UIKit控件添加signal。
這樣就能給控件添加訂閱了,比如 text field 的 rac_textSignalRACSignal的每個操作都會返回一個RACsignal,
這在術(shù)語上叫做連貫接口(fluent interface)。這個功
能可以讓你直接構(gòu)建管道,而不用每一步都使用本地變量。
片段解析:
-
只要 text 有變化, 將 text 發(fā)送給 Subscriber
[self.usernameTextField.rac_textSignal subscribeNext:^(id x){ NSLog(@"%@", x);}];
篩選長度 >3, 滿足則發(fā)送給 Subscriber
[[self.usernameTextField.rac_textSignal
filter:^BOOL(NSString *text){
return text.length > 3;
}]
subscribeNext:^(id x){
NSLog(@"%@", x);
}];
上面代碼如果按步驟來:
RACSignal *usernameSourceSignal =
self.usernameTextField.rac_textSignal;
RACSignal *filteredUsername = [usernameSourceSignal
filter:^BOOL(id value){
NSString*text = value;
return text.length > 3;
}];
[filteredUsername subscribeNext:^(id x){
NSLog(@"%@", x);
}];
-
在管道中添加map:
這里的 map 操作之后的步驟收到的都是NSNumber實例。
可以使用map操作來把接收的數(shù)據(jù)轉(zhuǎn)換成想要的類型,只要它是對象。**[[[self.usernameTextField.rac_textSignal map:^id(NSString*text){ return @(text.length); }] filter:^BOOL(NSNumber*length){ return[length integerValue] > 3; }] subscribeNext:^(id x){ NSLog(@"%@", x); }];
新加的map操作通過block改變了事件的數(shù)據(jù)。map從上一個next事件接收數(shù)據(jù),通過執(zhí)行block把返回值傳給下一個next事件。在上面的代碼中,map以NSString為輸入,取字符串的長度,返回一個NSNumber。
結(jié)尾:
簡明語法入門,圖文并茂:
http://www.teehanlax.com/blog/reactivecocoa/
參考:
http://benbeng.leanote.com/post/ReactiveCocoaTutorial-part1