ReactiveCocoa常見的類
RACSignal:信號(hào)類;RACSubscriber是協(xié)議
簡(jiǎn)介
有數(shù)據(jù)產(chǎn)生時(shí)就會(huì)使用RACSignal類
默認(rèn)是冷信號(hào),必須訂閱信號(hào)類
RACSignal使用步驟
創(chuàng)建信號(hào)(默認(rèn)創(chuàng)建的是冷信號(hào))
didSubscribe調(diào)用:只要一個(gè)信號(hào)被訂閱就會(huì)調(diào)用
didSubscribe作用:發(fā)送數(shù)據(jù)
訂閱信號(hào)(變?yōu)闊嵝盘?hào))subscribeNext:訂閱
nextBlock調(diào)用:只要訂閱者發(fā)送數(shù)據(jù)就會(huì)調(diào)用
nextBlock作用:處理數(shù)據(jù),展示在UI上面
發(fā)送信號(hào)(sendNext:)
只要訂閱者調(diào)用sendNext就會(huì)執(zhí)行nextBlock
只要訂閱RACDynamicSignal就會(huì)執(zhí)行didSubscribe
前提條件是RACDynamicSignal,不同類型信號(hào)的訂閱,處理訂閱的事情不一樣
RACSignal使用步驟:
1.創(chuàng)建信號(hào) + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe
2.訂閱信號(hào),才會(huì)激活信號(hào). - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.發(fā)送信號(hào) - (void)sendNext:(id)value
RACSignal底層實(shí)現(xiàn):
1.創(chuàng)建信號(hào)跳昼,首先把didSubscribe保存到信號(hào)中秀姐,還不會(huì)觸發(fā)理澎。
2.當(dāng)信號(hào)被訂閱,也就是調(diào)用signal的subscribeNext:nextBlock
2.2 subscribeNext內(nèi)部會(huì)創(chuàng)建訂閱者subscriber正歼,并且把nextBlock保存到subscriber中。
2.1 subscribeNext內(nèi)部會(huì)調(diào)用siganl的didSubscribe
3.siganl的didSubscribe中調(diào)用[subscriber sendNext:@1];
3.1 sendNext底層其實(shí)就是執(zhí)行subscriber的nextBlock
// 1.創(chuàng)建信號(hào)
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// block調(diào)用時(shí)刻:每當(dāng)有訂閱者訂閱信號(hào),就會(huì)調(diào)用block转砖。
// 2.發(fā)送信號(hào)
[subscriber sendNext:@1];
// 如果不在發(fā)送數(shù)據(jù),最好發(fā)送信號(hào)完成鲸伴,內(nèi)部會(huì)自動(dòng)調(diào)用[RACDisposable disposable]取消訂閱信號(hào)府蔗。
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// block調(diào)用時(shí)刻:當(dāng)信號(hào)發(fā)送完成或者發(fā)送錯(cuò)誤,就會(huì)自動(dòng)執(zhí)行這個(gè)block,取消訂閱信號(hào)汞窗。
// 執(zhí)行完Block后姓赤,當(dāng)前信號(hào)就不在被訂閱了。
NSLog(@"信號(hào)被銷毀");
}];
}];
// 3.訂閱信號(hào),才會(huì)激活信號(hào).
[siganl subscribeNext:^(id x) {
// block調(diào)用時(shí)刻:每當(dāng)有信號(hào)發(fā)出數(shù)據(jù)仲吏,就會(huì)調(diào)用block.
NSLog(@"接收到數(shù)據(jù):%@",x);
}];
2.? RACDisposable:取消訂閱
只要信號(hào)發(fā)送數(shù)據(jù)完畢就會(huì)自動(dòng)取消訂閱
只要訂閱者在就不會(huì)自動(dòng)取消信號(hào)的訂閱
調(diào)用[disposable dispose];就會(huì)取消
3.? RACSubject:信號(hào)提供者,自己可以充當(dāng)信號(hào),也可以充當(dāng)訂閱者
必須先訂閱再發(fā)送信號(hào)
使用場(chǎng)景: 通常用來代替代理,有了他就不必定義代理了
RACSubject使用步驟
1.創(chuàng)建信號(hào) [RACSubject subject]不铆,跟RACSiganl不一樣,創(chuàng)建信號(hào)時(shí)沒有block裹唆。
2.訂閱信號(hào) - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.發(fā)送信號(hào) sendNext:(id)value
RACSubject:底層實(shí)現(xiàn)和RACSignal不一樣狂男。
1.調(diào)用subscribeNext訂閱信號(hào),只是把訂閱者保存起來品腹,并且訂閱者的nextBlock已經(jīng)賦值了岖食。
2.調(diào)用sendNext發(fā)送信號(hào),遍歷剛剛保存的所有訂閱者舞吭,一個(gè)一個(gè)調(diào)用訂閱者的nextBlock泡垃。
// 1.創(chuàng)建信號(hào)
RACSubject *subject = [RACSubject subject];
// 2.訂閱信號(hào)
[subject subscribeNext:^(id x) {
// block調(diào)用時(shí)刻:當(dāng)信號(hào)發(fā)出新值析珊,就會(huì)調(diào)用.
NSLog(@"第一個(gè)訂閱者%@",x);
}];
[subject subscribeNext:^(id x) {
// block調(diào)用時(shí)刻:當(dāng)信號(hào)發(fā)出新值,就會(huì)調(diào)用.
NSLog(@"第二個(gè)訂閱者%@",x);
}];
// 3.發(fā)送信號(hào)
[subject sendNext:@"1"];
4.? RACReplaySubject: 重復(fù)提供信號(hào)類,是RACSubject的子類
RACReplaySubject可以先發(fā)送信號(hào)蔑穴,在訂閱信號(hào)忠寻,RACSubject就不可以。
使用場(chǎng)景一`:如果一個(gè)信號(hào)每被訂閱一次存和,就需要把之前的值重復(fù)發(fā)送一遍奕剃,使用重復(fù)提供信號(hào)類。
使用場(chǎng)景二`:可以設(shè)置capacity數(shù)量來限制緩存的value的數(shù)量,即只緩充最新的幾個(gè)值捐腿。
RACReplaySubject使用步驟:
1.創(chuàng)建信號(hào) [RACSubject subject]纵朋,跟RACSiganl不一樣,創(chuàng)建信號(hào)時(shí)沒有block茄袖。
2.可以先訂閱信號(hào)操软,也可以先發(fā)送信號(hào)。
2.1 訂閱信號(hào) - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
2.2 發(fā)送信號(hào) sendNext:(id)value
RACReplaySubject:底層實(shí)現(xiàn)和RACSubject不一樣宪祥。
1.調(diào)用sendNext發(fā)送信號(hào)聂薪,把值保存起來,然后遍歷剛剛保存的所有訂閱者蝗羊,一個(gè)一個(gè)調(diào)用訂閱者的nextBlock藏澳。
2.調(diào)用subscribeNext訂閱信號(hào),遍歷保存的所有值耀找,一個(gè)一個(gè)調(diào)用訂閱者的nextBlock
如果想當(dāng)一個(gè)信號(hào)被訂閱笆载,就重復(fù)播放之前所有值,需要先發(fā)送信號(hào)涯呻,在訂閱信號(hào)凉驻。也就是先保存值,在訂閱值复罐。
// 1.創(chuàng)建信號(hào)
RACReplaySubject *replaySubject = [RACReplaySubject subject];
// 2.發(fā)送信號(hào)
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
// 3.訂閱信號(hào)
[replaySubject subscribeNext:^(id x) {
NSLog(@"第一個(gè)訂閱者接收到的數(shù)據(jù)%@",x);
}];
// 訂閱信號(hào)
[replaySubject subscribeNext:^(id x) {
NSLog(@"第二個(gè)訂閱者接收到的數(shù)據(jù)%@",x);
}];
>>> RACSubject替換代理
需求:
1.給當(dāng)前控制器添加一個(gè)按鈕涝登,modal到另一個(gè)控制器界面
2.另一個(gè)控制器view中有個(gè)按鈕,點(diǎn)擊按鈕效诅,通知當(dāng)前控制器
步驟一:在第二個(gè)控制器.h胀滚,添加一個(gè)RACSubject代替代理。
@interface TwoViewController : UIViewController
@property (nonatomic, strong) RACSubject *delegateSignal;
@end
步驟二:監(jiān)聽第二個(gè)控制器按鈕點(diǎn)擊
@implementation TwoViewController
- (IBAction)notice:(id)sender {
// 通知第一個(gè)控制器乱投,告訴它咽笼,按鈕被點(diǎn)了
// 通知代理
// 判斷代理信號(hào)是否有值
if (self.delegateSignal) {
// 有值,才需要通知
[self.delegateSignal sendNext:nil];
}
}
@end
步驟三:在第一個(gè)控制器中戚炫,監(jiān)聽跳轉(zhuǎn)按鈕剑刑,給第二個(gè)控制器的代理信號(hào)賦值,并且監(jiān)聽.
@implementation OneViewController
- (IBAction)btnClick:(id)sender {
// 創(chuàng)建第二個(gè)控制器
TwoViewController *twoVc = [[TwoViewController alloc] init];
// 設(shè)置代理信號(hào)
twoVc.delegateSignal = [RACSubject subject];
// 訂閱代理信號(hào)
[twoVc.delegateSignal subscribeNext:^(id x) {
NSLog(@"點(diǎn)擊了通知按鈕");
}];
// 跳轉(zhuǎn)到第二個(gè)控制器
[self presentViewController:twoVc animated:YES completion:nil];
}
@end
5.? RACTuple: 元組類
RACSequence:集合類,用于代替NSArray,NSDictionary,可以用來快速遍歷數(shù)組和字典
// 1.遍歷數(shù)組
NSArray *numbers = @[@1,@2,@3,@4];
// 這里其實(shí)是三步
// 第一步: 把數(shù)組轉(zhuǎn)換成集合RACSequence numbers.rac_sequence
// 第二步: 把集合RACSequence轉(zhuǎn)換RACSignal信號(hào)類,numbers.rac_sequence.signal
// 第三步: 訂閱信號(hào),激活信號(hào)施掏,會(huì)自動(dòng)把集合中的所有值钮惠,遍歷出來。
[numbers.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 2.遍歷字典,遍歷出來的鍵值對(duì)會(huì)包裝成RACTuple(元組對(duì)象)
NSDictionary *dict = @{@"name":@"HMJ",@"age":@18};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
// 解包元組七芭,會(huì)把元組的值素挽,按順序給參數(shù)里面的變量賦值
RACTupleUnpack(NSString *key, NSString *value) = x;
// 相當(dāng)于以下寫法
//??????? NSString *key = x[0];
//??????? NSString *value = x[1];
NSLog(@"%@ %@",key,value);
}];
3.字典轉(zhuǎn)模型
3.1 OC寫法
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
NSMutableArray *items = [NSMutableArray array];
for (NSDictionary *dict in dictArr) {
FlagItem *item = [FlagItem flagWithDict:dict];
[items addObject:item];
}
3.2 RAC寫法
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
NSMutableArray *flags = [NSMutableArray array];
_flags = flags;
// rac_sequence注意點(diǎn):調(diào)用subscribeNext,并不會(huì)馬上執(zhí)行nextBlock狸驳,而是會(huì)等一會(huì)预明。
[dictArr.rac_sequence.signal subscribeNext:^(id x) {
// 運(yùn)用RAC遍歷字典,x:字典
FlagItem *item = [FlagItem flagWithDict:x];
[flags addObject:item];
}];
NSLog(@"%@",? NSStringFromCGRect([UIScreen mainScreen].bounds));
3.3 RAC高級(jí)寫法:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];
NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];
// map:映射的意思耙箍,目的:把原始值value映射成一個(gè)新值
// array: 把集合轉(zhuǎn)換成數(shù)組
// 底層實(shí)現(xiàn):當(dāng)信號(hào)被訂閱撰糠,會(huì)遍歷集合中的原始值,映射成新值究西,并且保存到新的數(shù)組里。
NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
return [FlagItem flagWithDict:value];
}] array];