RAC(Reactive Cocoa)常見的類

ReactiveCocoa常見的類

RACSignal:信號類;RACSubscriber是協(xié)議

簡介

有數(shù)據(jù)產(chǎn)生時就會使用RACSignal類

默認是冷信號,必須訂閱信號類

RACSignal使用步驟

創(chuàng)建信號(默認創(chuàng)建的是冷信號)

didSubscribe調(diào)用:只要一個信號被訂閱就會調(diào)用

didSubscribe作用:發(fā)送數(shù)據(jù)

訂閱信號(變?yōu)闊嵝盘?subscribeNext:訂閱

nextBlock調(diào)用:只要訂閱者發(fā)送數(shù)據(jù)就會調(diào)用

nextBlock作用:處理數(shù)據(jù),展示在UI上面

發(fā)送信號(sendNext:)

只要訂閱者調(diào)用sendNext就會執(zhí)行nextBlock

只要訂閱RACDynamicSignal就會執(zhí)行didSubscribe

前提條件是RACDynamicSignal,不同類型信號的訂閱,處理訂閱的事情不一樣

RACSignal使用步驟:

1.創(chuàng)建信號 + (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe

2.訂閱信號,才會激活信號. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock

3.發(fā)送信號 - (void)sendNext:(id)value

RACSignal底層實現(xiàn):

1.創(chuàng)建信號,首先把didSubscribe保存到信號中,還不會觸發(fā)。

2.當(dāng)信號被訂閱,也就是調(diào)用signal的subscribeNext:nextBlock

2.2 subscribeNext內(nèi)部會創(chuàng)建訂閱者subscriber,并且把nextBlock保存到subscriber中。

2.1 subscribeNext內(nèi)部會調(diào)用siganl的didSubscribe

3.siganl的didSubscribe中調(diào)用[subscriber sendNext:@1];

3.1 sendNext底層其實就是執(zhí)行subscriber的nextBlock

// 1.創(chuàng)建信號

RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {

// block調(diào)用時刻:每當(dāng)有訂閱者訂閱信號,就會調(diào)用block。

// 2.發(fā)送信號

[subscriber sendNext:@1];

// 如果不在發(fā)送數(shù)據(jù),最好發(fā)送信號完成,內(nèi)部會自動調(diào)用[RACDisposable disposable]取消訂閱信號。

[subscriber sendCompleted];

return [RACDisposable disposableWithBlock:^{

// block調(diào)用時刻:當(dāng)信號發(fā)送完成或者發(fā)送錯誤,就會自動執(zhí)行這個block,取消訂閱信號。

// 執(zhí)行完Block后,當(dāng)前信號就不在被訂閱了。

NSLog(@"信號被銷毀");

}];

}];

// 3.訂閱信號,才會激活信號.

[siganl subscribeNext:^(id x) {

// block調(diào)用時刻:每當(dāng)有信號發(fā)出數(shù)據(jù),就會調(diào)用block.

NSLog(@"接收到數(shù)據(jù):%@",x);

}];

2.? RACDisposable:取消訂閱

只要信號發(fā)送數(shù)據(jù)完畢就會自動取消訂閱

只要訂閱者在就不會自動取消信號的訂閱

調(diào)用[disposable dispose];就會取消

3.? RACSubject:信號提供者,自己可以充當(dāng)信號,也可以充當(dāng)訂閱者

必須先訂閱再發(fā)送信號

使用場景: 通常用來代替代理,有了他就不必定義代理了

RACSubject使用步驟

1.創(chuàng)建信號 [RACSubject subject],跟RACSiganl不一樣,創(chuàng)建信號時沒有block。

2.訂閱信號 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock

3.發(fā)送信號 sendNext:(id)value

RACSubject:底層實現(xiàn)和RACSignal不一樣。

1.調(diào)用subscribeNext訂閱信號,只是把訂閱者保存起來,并且訂閱者的nextBlock已經(jīng)賦值了。

2.調(diào)用sendNext發(fā)送信號,遍歷剛剛保存的所有訂閱者,一個一個調(diào)用訂閱者的nextBlock。

// 1.創(chuàng)建信號

RACSubject *subject = [RACSubject subject];

// 2.訂閱信號

[subject subscribeNext:^(id x) {

// block調(diào)用時刻:當(dāng)信號發(fā)出新值,就會調(diào)用.

NSLog(@"第一個訂閱者%@",x);

}];

[subject subscribeNext:^(id x) {

// block調(diào)用時刻:當(dāng)信號發(fā)出新值,就會調(diào)用.

NSLog(@"第二個訂閱者%@",x);

}];

// 3.發(fā)送信號

[subject sendNext:@"1"];

4.? RACReplaySubject: 重復(fù)提供信號類,是RACSubject的子類

RACReplaySubject可以先發(fā)送信號,在訂閱信號,RACSubject就不可以。

使用場景一`:如果一個信號每被訂閱一次,就需要把之前的值重復(fù)發(fā)送一遍,使用重復(fù)提供信號類。

使用場景二`:可以設(shè)置capacity數(shù)量來限制緩存的value的數(shù)量,即只緩充最新的幾個值。

RACReplaySubject使用步驟:

1.創(chuàng)建信號 [RACSubject subject],跟RACSiganl不一樣,創(chuàng)建信號時沒有block。

2.可以先訂閱信號,也可以先發(fā)送信號。

2.1 訂閱信號 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock

2.2 發(fā)送信號 sendNext:(id)value

RACReplaySubject:底層實現(xiàn)和RACSubject不一樣。

1.調(diào)用sendNext發(fā)送信號,把值保存起來,然后遍歷剛剛保存的所有訂閱者,一個一個調(diào)用訂閱者的nextBlock。

2.調(diào)用subscribeNext訂閱信號,遍歷保存的所有值,一個一個調(diào)用訂閱者的nextBlock

如果想當(dāng)一個信號被訂閱,就重復(fù)播放之前所有值,需要先發(fā)送信號,在訂閱信號。也就是先保存值,在訂閱值。

// 1.創(chuàng)建信號

RACReplaySubject *replaySubject = [RACReplaySubject subject];

// 2.發(fā)送信號

[replaySubject sendNext:@1];

[replaySubject sendNext:@2];

// 3.訂閱信號

[replaySubject subscribeNext:^(id x) {

NSLog(@"第一個訂閱者接收到的數(shù)據(jù)%@",x);

}];

// 訂閱信號

[replaySubject subscribeNext:^(id x) {

NSLog(@"第二個訂閱者接收到的數(shù)據(jù)%@",x);

}];

>>> RACSubject替換代理

需求:

1.給當(dāng)前控制器添加一個按鈕,modal到另一個控制器界面

2.另一個控制器view中有個按鈕,點擊按鈕,通知當(dāng)前控制器

步驟一:在第二個控制器.h,添加一個RACSubject代替代理。

@interface TwoViewController : UIViewController

@property (nonatomic, strong) RACSubject *delegateSignal;

@end

步驟二:監(jiān)聽第二個控制器按鈕點擊

@implementation TwoViewController

- (IBAction)notice:(id)sender {

// 通知第一個控制器,告訴它,按鈕被點了

// 通知代理

// 判斷代理信號是否有值

if (self.delegateSignal) {

// 有值,才需要通知

[self.delegateSignal sendNext:nil];

}

}

@end

步驟三:在第一個控制器中,監(jiān)聽跳轉(zhuǎn)按鈕,給第二個控制器的代理信號賦值,并且監(jiān)聽.

@implementation OneViewController

- (IBAction)btnClick:(id)sender {

// 創(chuàng)建第二個控制器

TwoViewController *twoVc = [[TwoViewController alloc] init];

// 設(shè)置代理信號

twoVc.delegateSignal = [RACSubject subject];

// 訂閱代理信號

[twoVc.delegateSignal subscribeNext:^(id x) {

NSLog(@"點擊了通知按鈕");

}];

// 跳轉(zhuǎn)到第二個控制器

[self presentViewController:twoVc animated:YES completion:nil];

}

@end

5.? RACTuple: 元組類

RACSequence:集合類,用于代替NSArray,NSDictionary,可以用來快速遍歷數(shù)組和字典

// 1.遍歷數(shù)組

NSArray *numbers = @[@1,@2,@3,@4];

// 這里其實是三步

// 第一步: 把數(shù)組轉(zhuǎn)換成集合RACSequence numbers.rac_sequence

// 第二步: 把集合RACSequence轉(zhuǎn)換RACSignal信號類,numbers.rac_sequence.signal

// 第三步: 訂閱信號,激活信號,會自動把集合中的所有值,遍歷出來。

[numbers.rac_sequence.signal subscribeNext:^(id x) {

NSLog(@"%@",x);

}];

// 2.遍歷字典,遍歷出來的鍵值對會包裝成RACTuple(元組對象)

NSDictionary *dict = @{@"name":@"HMJ",@"age":@18};

[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {

// 解包元組,會把元組的值,按順序給參數(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ào)用subscribeNext,并不會馬上執(zhí)行nextBlock,而是會等一會。

[dictArr.rac_sequence.signal subscribeNext:^(id x) {

// 運用RAC遍歷字典,x:字典

FlagItem *item = [FlagItem flagWithDict:x];

[flags addObject:item];

}];

NSLog(@"%@",? NSStringFromCGRect([UIScreen mainScreen].bounds));

3.3 RAC高級寫法:

NSString *filePath = [[NSBundle mainBundle] pathForResource:@"flags.plist" ofType:nil];

NSArray *dictArr = [NSArray arrayWithContentsOfFile:filePath];

// map:映射的意思,目的:把原始值value映射成一個新值

// array: 把集合轉(zhuǎn)換成數(shù)組

// 底層實現(xiàn):當(dāng)信號被訂閱,會遍歷集合中的原始值,映射成新值,并且保存到新的數(shù)組里。

NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {

return [FlagItem flagWithDict:value];

}] array];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容