所有的RACSignal都可以進行操作處理,因為所有的操作方法都定義在Stream.h中,因此只要繼承了RACStream就有了操作處理的方法
ReactiveCocoa操作思想:
- Hook(鉤子)思想:改變API(應用程序編程接口,也就是方法)執(zhí)行結(jié)果
一、ReactiveCocoa核心方法:bind
- ReactiveCocoa的核心方法是bind(綁定),也是RAC的核心開發(fā)方式
- 之前我們用的開發(fā)方式是賦值,現(xiàn)在我們創(chuàng)建對象的時候,就綁定好以后要做的事情,而不是等待賦值之后在做事情
- 我們之前展示數(shù)據(jù)到控件上,都是重寫setModel方法,而RAC在一開始創(chuàng)建控件時就綁定好了數(shù)據(jù)。
- 實際開發(fā)中很少用bind方法,因為bind是RAC底層方法,而RAC已經(jīng)封裝了很多其他方法供我們調(diào)用
// 需求:每次在文本框的輸入后面+sun
[[_textField.rac_textSignal bind:^RACSignalBindBlock _Nonnull{
return ^RACSignal *(id value, BOOL *stop){
// 信號一改變,就會執(zhí)行,并且把值傳遞過來
NSString *result = [NSString stringWithFormat:@"%@%@",value,@"sun"];
return [RACReturnSignal return:result];
};
}] subscribeNext:^(id _Nullable x) {
NSLog(@"獲取到處理完的數(shù)據(jù) %@",x);
}];
二、ReactiveCocoa操作方法之映射(flattenMap,map)
- map方法是對于flattenMap方法的封裝,flattenMap是對于bind方法的封裝,攔截源信號的內(nèi)容,改變后傳出
- map的block的返回值類型為id,flattenMap的block的返回值類型為RACSignal
- 給訂閱者發(fā)出的值不是信號,一般使用map
- 給訂閱者發(fā)出的值是信號,一般使用flatternMap
- map的簡單使用
[[_textField.rac_textSignal map:^id _Nullable(NSString * _Nullable value) {
NSString *result = [NSString stringWithFormat:@"xmg %@",value];
return result;
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- flattenMap的簡單使用
[[_textField.rac_textSignal flattenMap:^ RACSignal * (NSString * value) {
NSString *result = [NSString stringWithFormat:@"sun %@",value];
return [RACReturnSignal return:result];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
- 當遇到信號中的信號時,要使用flattenMap,map結(jié)合
[[signalOfSignals flattenMap:^RACSignal *(id value) {
return [value map:^id _Nullable(id _Nullable value) {
return [NSString stringWithFormat:@"XMG:%@",value];
}];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"1-%@",x);
}];
三、ReactiveCocoa操作方法之組合
3.1.concat
-
[signalA concat: signalB]
把兩個信號合并為一個信號,當signalA的事件完成,才能觸發(fā)signalB的事件 - 訂閱后,先接收到signalA的信息,然后接收到signalB的信息
- 方法內(nèi)部直接訂閱了signalA
- 應用場景: 需要把兩次請求的數(shù)據(jù)添加到一個數(shù)組,先添加A, 在添加B
concat語法:
// 創(chuàng)建信號
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACReplaySubject subject];
NSMutableArray *arrM = [NSMutableArray array];
// concat
[[signalA concat: signalB] subscribeNext:^(id _Nullable x) {
[arrM addObject:x];
}];
// 發(fā)送信號
[signalB sendNext:@"B"];
[signalA sendNext:@"A"];
[signalA sendCompleted];
3.2.then
- 當 前面一個信號的事件完成,才能觸發(fā)then后面信號的事件
- 訂閱后, 只能接收到后一個信號給訂閱者的信息
- 原理:使用concat連接then返回的信號,忽略之前信號發(fā)出的信息
then語法:
RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
[[signalA then:^RACSignal * _Nonnull{
return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
[subscriber sendNext:@2];
return nil;
}];
}] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
3.3.merge
- 把多個信號合并為一個信號, 任何一個信號給訂閱者發(fā)送信息都能監(jiān)聽到
// 無序的整合信號數(shù)據(jù)
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
[[signalA merge:signalB] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
// 發(fā)送
[signalB sendNext:@"B"];
[signalA sendNext:@"A"];
3.4.zipWith
- 把兩個個信號壓縮成一個信號,只有當 兩個信號都給訂閱者發(fā)送數(shù)據(jù)時,才能監(jiān)聽到
- 返回的x為元組
RACSubject *signalA = [RACSubject subject];
RACSubject *signalB = [RACSubject subject];
[[signalA zipWith:signalB] subscribeNext:^(id _Nullable x) {
RACTupleUnpack(NSString *a,NSString *b) = x;
NSLog(@"%@ %@",a,b);
}];
[signalA sendNext:@"A"];
[signalB sendNext:@"B"];
3.5.combineLatest (組合)
- 把兩個信號組合成一個信號時,和zip一樣
- 把多個信號合并為一個信號,只有當 所有信號都給訂閱者發(fā)送數(shù)據(jù)時,才能監(jiān)聽到
- 訂閱后,得到的是各個信號的最新值
- 返回的x為元組
[[_accountField.rac_textSignal combineLatestWith:_pwdField.rac_textSignal] subscribeNext:^(id _Nullable x) {
RACTupleUnpack(NSString *account,NSString *pwd) = x;
_loginButton.enabled = account.length > 0 && pwd.length;
}];
3.6.reduce(聚合)
- reduce后的block參數(shù)是自己寫上去的。有幾個信號,就寫幾個參數(shù),每個參數(shù)都是信號給訂閱者發(fā)送的數(shù)據(jù)
- 底層實現(xiàn):訂閱聚合信號,每次有內(nèi)容發(fā)出,就會執(zhí)行reduce的blcok,把信號內(nèi)容轉(zhuǎn)換成blcok返回的值。
- 把多個信號給訂閱者發(fā)送的數(shù)據(jù)聚合到一起
// 常見用法:先組合再聚合
[[RACSignal combineLatest:@[_accountField.rac_textSignal,_pwdField.rac_textSignal]
reduce:^id (NSString *account, NSString *pwd){
//這里返回什么,下面Block的x就是什么
return @(account.length > 0 && pwd.length > 0);
}] subscribeNext:^(id _Nullable x) {
_loginButton.enabled = [x boolValue];
}];
四、ReactiveCocoa核心操作方法-filter(過濾)
- 減少使用if
- 返回YES才可以給訂閱者發(fā)送數(shù)據(jù)
[[_pwdField.rac_textSignal filter:^BOOL (NSString *value) {
// 必須要滿足這個條件,才可以給訂閱者發(fā)送數(shù)據(jù)
return value.length > 6;
}] subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@",x);
}];
五、ReactiveCocoa核心操作方法-定時器
interval: onScheduler:
- RACScheduler:多線程,管理多線程
[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]]
subscribeNext:^(NSDate * _Nullable x) {
NSLog(@"執(zhí)行了定時器");
}];
六、ReactiveCocoa核心操作方法-delay(延遲執(zhí)行)
// 延遲發(fā)送數(shù)據(jù)
[[[RACSignal createSignal:^RACDisposable *(id <RACSubscriber> subscriber) {
[subscriber sendNext:@"hello"];
return nil;
}] delay:2] subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];
遵循NSFastEnumeration協(xié)議的可以當做數(shù)組