關於 ReactiveCocoa 的介紹,網路上已經有許多資源可以參考,
想要特別提醒的是,目前在 ReactiveCocoa 的官方 GitHub 中,
有分 ReactiveCocoa, ReactiveSwift, ReactiveObjC 等 repo,
原因是從 ReactiveCocoa 3.0 開始便只支援 Swift 語法。
所以如果想使用單純 Objective-C 的版本,目前最穩定的版本為 2.5。
以下的範例都是使用 2.5 版本的 ReactiveObjC。
Signal
Signal 是 ReactiveCocoa 的主要基本概念,
創建 Signal 以及訂閱 Signal ,而資料的流向會以 Signal 發送至訂閱對象。
Create Signal & Subscribe Signal
以下為創建 Signal 以及訂閱 Signal 的範例,
其中 createSignal 可以回傳一個 RACDisposable 的 block,
這個 block 會在此 Signal 結束或取消後執行。
sendNext 會將 value 傳送至訂閱對象的 subscribeNext block 中。
RACSignal *skSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"123"];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
}];
}];
[skSignal subscribeNext:^(id x) {
}];
RAC()
RAC 可將 object 的 property 訂閱 Signal,透過 Signal 最後回傳的 value 來取代此 property。
RACSignal *skSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"123"];
[subscriber sendCompleted];
return nil;
}];
NSLog(@"%@",self.value);
RAC(self,value) = skSignal;
NSLog(@"%@",self.value);
RACObserve()
RACObserve 會產生一個 Signal,此 Signal 可直接綁定某個 Object 的 property。
RACObserve(self, self.value);
配合 RAC(),就可以讓某個 object 的 property 去訂閱另外一個 object 的 value。
RAC(object1, object1.value) = RACObserve(object2, object2.value);
Signal Flow
可以串起多個 Signal 成為一個可處理複雜資料的程序。
- then
當 Signal 處理完成後,可以使用 then 在後面接上另外一個 Signal。
有幾點要特別說明。
- sendNext 與 sendCompleted 會由最後一個處理的 Signal 送給訂閱對象。
- 前一個 Signal 一定要執行 sendCompleted 才會交由下一個 Signal 執行。
- 若前一個 Singal 執行 sendError,便會停下程序,並傳送 error 給訂閱對象。
RACSignal s = [[RACSignal createSignal:^RACDisposable (id<RACSubscriber> subscriber) { [subscriber sendNext:@"1"]; [subscriber sendCompleted]; return nil; }] then:^RACSignal { return [RACSignal createSignal:^RACDisposable (id<RACSubscriber> subscriber) { [subscriber sendNext:@"2"]; [subscriber sendCompleted]; return nil; }]; }];
- doNext
doNext 的 block 會在 Signal sendNext 前先被執行。
且 sendNext 的 value 也會被帶到 doNext 的 block 中。
RACSignal *s = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
NSLog(@"123");
}];
- map
map 的功能是在 Signal sendNext 時先將 value 帶到 map block 中,
最後回傳一個新的 value。
RACSignal *s = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}] map:^id(id value) {
return @"4";
}];
- flattenMap
flattenMap 基本流程與 then 相同,差別在於可直接將前一個 Signal 的結果傳遞給下一個 Signal 來處理。
RACSignal *s = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}] flattenMap:^RACStream *(id value) {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}];
}];
- initially
初始化的 block 可以在執行 Signal 先被執行。
RACSignal *s = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"2"];
[subscriber sendCompleted];
return nil;
}] initially:^{
NSLog(@"123");
}];