ReactiveCocoa
前言
- 在 iOS 編程中我們需要處理各種事件,例如響應(yīng)按鈕的點(diǎn)擊,監(jiān)聽鍵盤的輸入,監(jiān)聽網(wǎng)絡(luò)回包等...我們通常使用
Cocoa
推薦的例如target-action
徒河、delegate
进胯、key-value observing
衡创、callback
等。 - ReactiveCocoa為我們提供了一種統(tǒng)一化的解決此類問(wèn)題的方式,使用RAC解決問(wèn)題峡蟋,就不需要考慮調(diào)用順序,直接考慮結(jié)果华望,把每一次操作都寫成一系列嵌套的方法中蕊蝗,使代碼高聚合,方便管理赖舟。
-
ReactiveCocoa將所有
Cocoa
中的事件都定義為了信號(hào)(single)蓬戚,從而可以使用一些基本工具來(lái)更容易的連接、過(guò)濾和組合.
參考博文:
RAC中涉及到的編程思想:
函數(shù)式編程(functional programming):使用高階函數(shù)宾抓,例如函數(shù)用其他函數(shù)作為參數(shù)子漩。
響應(yīng)式編程(reactive programming):關(guān)注于數(shù)據(jù)流和變化傳播。不需要考慮事件的調(diào)用過(guò)程,只需要關(guān)注數(shù)據(jù)的流入和輸出.
所以石洗,你可能聽說(shuō)過(guò)reactivecocoa被描述為函數(shù)響應(yīng)式編程(**FRP**)框架幢泼。
其他平臺(tái)上也有類似的框架例如java的****RXJava****_ swift中的__**_ReactiveSwif**
-
鏈?zhǔn)骄幊?/strong> : 是將多個(gè)操作(多行代碼)通過(guò)點(diǎn)號(hào)(.)鏈接在一起成為一句代碼,使代碼可讀性好。a(1).b(2).c(3),注意點(diǎn):要想達(dá)到鏈?zhǔn)骄幊谭椒ǖ姆祷刂当仨毷且粋€(gè)( (返回值是本身對(duì)象的)
block
),典型代表就是Masonry框架
RAC框架的結(jié)構(gòu)(直接略過(guò))
RAC中重要的類
RAC最重要的類是RACSingle(信號(hào)類)
- 它本身不具備發(fā)送信號(hào)的能力讲衫,而是交給內(nèi)部一個(gè)訂閱者(
id <RACSubscriber>
)去發(fā)出缕棵。 - 默認(rèn)一個(gè)信號(hào)創(chuàng)建出來(lái)都是冷信號(hào),即使是值改變了涉兽,也不會(huì)觸發(fā)招驴,只有訂閱了這個(gè)信號(hào),這個(gè)信號(hào)才會(huì)變?yōu)闊嵝盘?hào)枷畏,值改變了就會(huì)觸發(fā)
- RACSignal的每個(gè)操作都會(huì)返回一個(gè)RACsignal别厘,這在術(shù)語(yǔ)上叫做連貫接口(fluent interface),從而實(shí)現(xiàn)
鏈?zhǔn)骄幊?/code>
所以這里著重介紹一下RACSingle的創(chuàng)建和訂閱的實(shí)現(xiàn),從而理解信號(hào)的創(chuàng)建以及數(shù)據(jù)的傳遞過(guò)程
//這里用到一個(gè)工廠方法將子類實(shí)例返回回去
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
}
//我們?cè)賮?lái)看看子類`RACDynamicSignal`中的具體實(shí)現(xiàn),其實(shí)就是吧傳遞過(guò)來(lái)的didSubscribe這個(gè)block保存起來(lái)
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
方法的參數(shù)didSubscribe
這個(gè)block 可以理解為是對(duì)信號(hào)的描述,
上面只是信號(hào)的創(chuàng)建過(guò)程,上面提到了默認(rèn)信號(hào)被創(chuàng)建出來(lái)以后只是冷信號(hào),也就是didSubscribe這個(gè)block只有當(dāng)RACSingle調(diào)用subscribeNext:方法是才會(huì)調(diào)用,方法里的subscriber有三種方法,也可以理解為可以發(fā)送三種信號(hào)分別為:next、error拥诡、completed,
其中sendNext()
是發(fā)送我們需要傳遞的對(duì)象,sendError
,和sendComplete
都會(huì)中斷信號(hào)的訂閱.不同的是sendError
會(huì)傳遞一個(gè)錯(cuò)誤值error
.一個(gè)signal
在因error
終止或者sendComplete
前触趴,可以發(fā)送任意數(shù)量的next
事件
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock;
下面我們?cè)賮?lái)看看:subscribeNext:方法的實(shí)現(xiàn)過(guò)程:
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock
error:NULL
completed:NULL];
return [self subscribe:o];
}
這里首先創(chuàng)建一個(gè)RACSubscriber對(duì)象,這個(gè)是遵守了RACSubscriber協(xié)議的RACSubscriber *類型的對(duì)象,這個(gè)對(duì)象會(huì)將傳遞進(jìn)來(lái)的nextBlock保存起來(lái)(也是保存成成員變量),當(dāng)創(chuàng)建對(duì)象時(shí)候的didSubscribe中的"subscriber"調(diào)用sendNext:的時(shí)候nextBlock就會(huì)被調(diào)用! 有點(diǎn)繞,這里只是介紹了其中大概的工作原理,其中還有RACScheduler的參與,這里就不做介紹了..
RAC為cocoa中的很多類通過(guò)分類的形式快速生成信號(hào)以及常見的宏使用:
@weakify(self) & @strongify(self): Weak & Strong dance
RACObserve(TARGET, KEYPATH) & RAC(TARGET, ...) :這對(duì)宏簡(jiǎn)直是絕配類似KVC的用法,能夠快速地實(shí)現(xiàn)對(duì)象屬性的映射
//e.g.
RAC(self.titleLabel,text) = [RACObserve(self.viewModel, title);
rac_signalForSelector : 執(zhí)行某一個(gè)方法就會(huì)生成信號(hào)
rac_valuesAndChangesForKeyPath:用于監(jiān)聽某個(gè)對(duì)象的屬性改變氮发。
rac_signalForControlEvents:替代UIControl中的Target模式
rac_addObserverForName用于監(jiān)聽某個(gè)通知。
RACTuplePack(...)快速包裝成元祖類,成對(duì)出現(xiàn)的有RACTupleUnpack(...)
RACTuple *tuple = RACTuplePack(@"xmg",@20);
RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
rac_liftSelector:withSignalsFromArray:Signals:
應(yīng)用場(chǎng)景: 當(dāng)界面有多個(gè)請(qǐng)求的時(shí)候,當(dāng)所有的請(qǐng)求都回包時(shí)才出發(fā)某個(gè)操作
RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { // 發(fā)送請(qǐng)求1 ,并且獲取到數(shù)據(jù)以后: [subscriber sendNext:@"發(fā)送請(qǐng)求1"]; return nil; }]; RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { // 發(fā)送請(qǐng)求2 ,并且獲取到數(shù)據(jù)以后: [subscriber sendNext:@"發(fā)送請(qǐng)求2"]; return nil; }]; // 使用注意:updateUIWithR1::中的參數(shù)和信號(hào)所傳遞過(guò)來(lái)的數(shù)據(jù)一一對(duì)應(yīng) [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];
RACSubject類
-
RACSubject既是信號(hào)(繼承自RACSingle類),又是訂閱者(遵循
<RACSubscriber>
),通常使用RACSubject類來(lái)代替代理,其實(shí)我感覺(jué)代替通知都可以
RACSubject *subject = [RACSubject subject];
[subject subscribeNext:^(id x) {
NSLog(@"第一個(gè)訂閱者%@",x);
}];
[subject subscribeNext:^(id x) {
NSLog(@"第二個(gè)訂閱者%@",x);
}];
[subject sendNext:@"1"];
- RACReplaySubject:重復(fù)提供信號(hào)類雕蔽,RACSubject的子類折柠。
RACReplaySubject與RACSubject區(qū)別: RACReplaySubject可以先發(fā)送信號(hào),在訂閱信號(hào)批狐,RACSubject就不可以扇售。如果一個(gè)信號(hào)每被訂閱一次,就需要把之前的值重復(fù)發(fā)送一遍嚣艇,使用重復(fù)提供信號(hào)類承冰。
RAC中的集合類RACSequence
RACSequence是RAC中的集合類,可以實(shí)現(xiàn)OC對(duì)象與信號(hào)中傳遞值之間的轉(zhuǎn)換,RAC類庫(kù)中提供了NSArray,NSDictionary等集合類的分類供其轉(zhuǎn)換
//遍歷數(shù)組
NSArray *numbers = @[@1,@2,@3,@4];
[numbers.rac_sequence.signal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//遍歷字典
NSDictionary *dict = @{@"name":@"qdaily",@"age":@3};
[dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
RACTupleUnpack(NSString *key,NSString *value) = x;
NSLog(@"%@ %@",key,value);
}];
RACTupleUnpack將RACTuple進(jìn)行解包
//使用map方法可以快速進(jìn)行字典轉(zhuǎn)模型
NSArray *flags = [[dictArr.rac_sequence map:^id(id value) {
return [FlagItem flagWithDict:value];
}] array];
RACCommand:RAC中用于處理事件的類
可以理解為命令類,是對(duì)信號(hào)和事件的封裝
使用場(chǎng)景:監(jiān)聽按鈕點(diǎn)擊,網(wǎng)絡(luò)請(qǐng)求
RACCommand使用注意點(diǎn):
- signalBlock必須要返回一個(gè)信號(hào)食零,不能傳nil.
- 如果不想要傳遞信號(hào)困乒,直接創(chuàng)建空的信號(hào)[RACSignal empty];
- RACCommand中信號(hào)如果數(shù)據(jù)傳遞完,必須調(diào)用[subscriber sendCompleted]贰谣,這時(shí)命令才會(huì)執(zhí)行完畢娜搂,否則永遠(yuǎn)處于執(zhí)行中。
- RACCommand需要被強(qiáng)引用吱抚,否則接收不到RACCommand中的信號(hào)百宇,因此RACCommand中的信號(hào)是延遲發(fā)送的。
RACCommand簡(jiǎn)單使用
RACCommand *requestCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
NSLog(@"請(qǐng)求數(shù)據(jù)ing...");
//這里即使不需要傳遞值也要?jiǎng)?chuàng)建空的信號(hào)而不能返回nil
// return [RACSignal empty];
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"請(qǐng)求數(shù)據(jù)"];
// 注意:數(shù)據(jù)傳遞完秘豹,最好調(diào)用sendCompleted携御,這時(shí)命令才執(zhí)行完畢。
[subscriber sendCompleted]; return nil;
}];
}];
// 強(qiáng)引用命令既绕,不要被銷毀啄刹,否則接收不到數(shù)據(jù),這個(gè)command屬性一般暴露給外界
_conmmand = command;
//下面通常是外面調(diào)用
[command.executionSignals subscribeNext:^(id x) {
[x subscribeNext:^(id x) {
NSLog(@"網(wǎng)絡(luò)獲取的值是:%@",x);
}];
}];
// RACCommand高級(jí)用法
// switchToLatest:用于signal of signals,獲取signal of signals發(fā)出的最新信號(hào),也就是可以直接拿到RACCommand中的信號(hào) [command.executionSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//executing 監(jiān)聽命令是否執(zhí)行完畢,默認(rèn)會(huì)來(lái)一次凄贩,可以直接跳過(guò)誓军,skip表示跳過(guò)第一次信號(hào)。
[[command.executing skip:1] subscribeNext:^(id x) {
if ([x boolValue] == YES) {
// 正在執(zhí)行 NSLog(@"正在執(zhí)行");
}else{
// 執(zhí)行完成 NSLog(@"執(zhí)行完成");
}
}];
RACMuticastConnection
RACMulticastConnection:用于當(dāng)一個(gè)信號(hào)疲扎,被多次訂閱時(shí)谭企,為了保證創(chuàng)建信號(hào)時(shí),避免多次調(diào)用創(chuàng)建信號(hào)中的block评肆,造成副作用债查,可以使用這個(gè)類處理。
- 普通的訂閱信號(hào)過(guò)程:
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"發(fā)送請(qǐng)求");
return nil;
}];
// 第一次訂閱信號(hào)
[signal subscribeNext:^(id x) {
NSLog(@"接收數(shù)據(jù)");
}];
// 第二次訂閱信號(hào)
[signal subscribeNext:^(id x) {
NSLog(@"接收數(shù)據(jù)");
}];
// 3.運(yùn)行結(jié)果:打印兩次@"發(fā)送請(qǐng)求"瓜挽,也就是每次訂閱都會(huì)發(fā)送一次請(qǐng)求
- RACMulticastConnection:解決重復(fù)請(qǐng)求問(wèn)題
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSLog(@"發(fā)送請(qǐng)求");
[subscriber sendNext:@1];
return nil;
}];
RACMulticastConnection *connect = [signal publish];
// 注意:訂閱信號(hào)盹廷,也不能激活信號(hào),只是保存訂閱者到數(shù)組久橙,必須通過(guò)連接,當(dāng)調(diào)用連接俄占,就會(huì)一次性調(diào)用所有訂閱者的sendNext:
[connect.signal subscribeNext:^(id x) {
NSLog(@"訂閱者一信號(hào)");
}];
[connect.signal subscribeNext:^(id x) {
NSLog(@"訂閱者二信號(hào)");
}];
[connect connect];
//運(yùn)行結(jié)果:只會(huì)打印一次@"發(fā)送請(qǐng)求"
RAC中信號(hào)處理的常用方法
RAC 核心方法綁定bind
對(duì)比之前的開發(fā)方式是賦值管怠,而用RAC開發(fā),應(yīng)該把重心放在綁定缸榄,也就是在創(chuàng)建一個(gè)對(duì)象的時(shí)候渤弛,就綁定好以后想要做的事情,而不是等賦值之后在去做事情甚带。
列如:把數(shù)據(jù)展示到控件上她肯,之前都是重寫控件的setModel方法,用RAC就可以在一開始創(chuàng)建控件的時(shí)候鹰贵,就綁定好數(shù)據(jù)晴氨。
注意:在開發(fā)中很少使用
bind
方法,bind
屬于RAC中的底層方法碉输,RAC已經(jīng)封裝了很多好用的其他方法籽前,底層都是調(diào)用bind,用法比bind簡(jiǎn)單.
下面例子中要實(shí)現(xiàn)當(dāng) testField 的文字改變以后每次輸出"輸出:**",下面的信號(hào)訂閱方法底層會(huì)轉(zhuǎn)換成bind方法
//使用 bind 方法
[[_textField.rac_textSignal bind:^RACStreamBindBlock{
return ^RACStream *(id value, BOOL *stop){
return [RACReturnSignal return:[NSString stringWithFormat:@"輸出:%@",value]];
};
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//直接訂閱信號(hào)
[_textField.rac_textSignal subscribeNext:^(id x) { NSLog(@"輸出:%@",x); }];
過(guò)濾信號(hào)的操作
fliter : 過(guò)濾信號(hào)(條件過(guò)濾)
- 通過(guò)返回bool的方式控制是否接受信號(hào)傳遞過(guò)來(lái)的值(控制是否調(diào)用
subscribeNext
這個(gè)block)- fliter會(huì)將接受的信號(hào)通過(guò)返回的條件進(jìn)行篩選,并且生成新的信號(hào)供訂閱者訂閱.
- 從fliter的使用中可以看出
RAC
中對(duì)信號(hào)的操作都會(huì)生成新的信號(hào),以便達(dá)到鏈?zhǔn)骄幊痰哪康?/li>- 從這點(diǎn)建議在對(duì)信號(hào)的操作的代碼書寫規(guī)范:每一次操作都應(yīng)該折行,這樣閱讀起來(lái)更加清晰
本例中要實(shí)現(xiàn)當(dāng)用戶名長(zhǎng)度大于3的時(shí)候輸出log
[[self.usernameTextField.rac_textSignal
filter:^BOOL(id value){
NSString*text = value;
return text.length > 3;
}] subscribeNext:^(id x){
NSLog(@"%@", x);
}];
ignore:
忽略某些信號(hào)的值
// 內(nèi)部調(diào)用filter過(guò)濾敷钾,忽略掉ignore的值 [[_textField.rac_textSignal ignore:@"1"]
subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
distinctUntilChanged:
當(dāng)上一次的值和當(dāng)前的值有明顯的變化就會(huì)發(fā)出信號(hào), 在開發(fā)中枝哄,刷新UI經(jīng)常使用,只有兩次數(shù)據(jù)不一樣才需要刷新,提高性能,減少不必要的操作
[[_textField.rac_textSignal distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
take
從信號(hào)發(fā)出的值中取前n個(gè)
RACSubject *signal = [RACSubject subject];
[[signal take:1] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signal sendNext:@1];
[signal sendNext:@2];
takeLast:
取最后N次的信號(hào),前提條件阻荒,由于是從信號(hào)的后面取,所以訂閱者必須調(diào)用完成挠锥,因?yàn)橹挥型瓿桑椭揽偣灿卸嗌傩盘?hào).
RACSubject *signal = [RACSubject subject];
[[signal takeLast:1] subscribeNext:^(id x)
NSLog(@"%@",x);
}];
[signal sendNext:@1];
[signal sendNext:@2];
//必須有下一步!
[signal sendCompleted];
takeUntil:(RACSignal *):
獲取信號(hào)直到某個(gè)信號(hào)執(zhí)行完成
[_textField.rac_textSignal
takeUntil:self.rac_willDeallocSignal];
skip:(NSUInteger):
跳過(guò)幾個(gè)信號(hào),不接受财松。
// 表示輸入第一次,不會(huì)被監(jiān)聽到纱控,跳過(guò)第一次發(fā)出的信號(hào)
[[_textField.rac_textSignal skip:1] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
switchToLatest:
用于signalOfSignals(信號(hào)的信號(hào))辆毡,有時(shí)候信號(hào)也會(huì)發(fā)出信號(hào),會(huì)在signalOfSignals中甜害,獲取signalOfSignals發(fā)送的最新信號(hào)舶掖。
RACSubject *signalOfSignals = [RACSubject subject];
RACSubject *signal = [RACSubject subject];
// 獲取信號(hào)中信號(hào)最近發(fā)出信號(hào),訂閱最近發(fā)出的信號(hào)尔店。
// 注意switchToLatest:只能用于信號(hào)中的信號(hào)
[signalOfSignals.switchToLatest subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
[signalOfSignals sendNext:signal];
[signal sendNext:@1];
Map:
(映射) map能夠"加工信號(hào)傳遞的值”
這里的加工信號(hào)指的是將上一個(gè)next事件傳遞過(guò)來(lái)的信號(hào)值x進(jìn)行加工或者轉(zhuǎn)換成任意的OC對(duì)象,通過(guò)block返回值返回回去,這個(gè)例子中就是將用戶名加工成NSNumber值返回回去,所以下一個(gè)next事件接收到的值就是NSNumber對(duì)象.
[[[self.usernameTextField.rac_textSignal
map:^id(NSString*text){
return @(text.length);
}]
filter:^BOOL(NSNumber*length){
return[length integerValue] > 3;
}]
subscribeNext:^(id x){
NSLog(@"%@", x):
}];
//test2
[[validPasswordSignal
map:^id(NSNumber *passwordValid){
return[passwordValid boolValue] ? [UIColor clearColor]:[UIColor yellowColor];
}]
subscribeNext:^(UIColor *color){
self.passwordTextField.backgroundColor = color;
}];
flatten map: 信號(hào)的映射
flatten可以對(duì)傳遞過(guò)來(lái)的信號(hào)進(jìn)行加工,會(huì)重新新建一個(gè)信號(hào),block中的返回值是一個(gè)信號(hào)
[[_textField.rac_textSignal flattenMap:^RACStream *(id value) {
return [RACReturnSignal return:[NSString stringWithFormat:@"輸出:%@",value]]; }]
subscribeNext:^(id x) {
}];
flattenMap 和 Map 方法的區(qū)別:
- flattenMap方法中的block返回值是信號(hào),所以是對(duì)信號(hào)的加工
- Map 方法中的block的返回值是對(duì)象,是對(duì)信號(hào)傳遞的變量的加工
- 一般如果傳遞的是對(duì)象,使用map,信號(hào)傳遞的是信號(hào)就用flattenMap
Reduce
聚合: 將多個(gè)信號(hào)發(fā)出的值進(jìn)行聚合
常用用法:通常使用
+ (RACSignal *)combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock;
將多個(gè)信號(hào)進(jìn)行聚合,在reduceBlock
中將信號(hào)傳遞的值
進(jìn)行整合.這個(gè)方法會(huì)創(chuàng)建一個(gè)新的信號(hào)攜帶整合好的值返回,每次這兩個(gè)源信號(hào)的任何一個(gè)產(chǎn)生新值時(shí)眨攘,reduce block都會(huì)執(zhí)行,block的返回值會(huì)發(fā)給下一個(gè)信號(hào)嚣州。常見應(yīng)用場(chǎng)景就是登錄界面是否滿足登錄條件從而控制登錄按鈕的狀態(tài)
注意這個(gè)方法中的reduceBlock: 這個(gè)block是一個(gè)返回值為id類型的,也就是說(shuō)我們將需要聚合的信號(hào)攜帶的值進(jìn)行加工組合以后一定要返回一個(gè)新的對(duì)象,combineLatest::這個(gè)方法返回的信號(hào)會(huì)攜帶這個(gè)新對(duì)象! 我們?cè)僮⒁饪?code>reduceBlock中的參數(shù),參數(shù)個(gè)數(shù)是不確定的,他們和信號(hào)中攜帶的值一一對(duì)應(yīng),為了實(shí)現(xiàn)這個(gè)功能RAC中專門有個(gè)
RACBlockTrampoline
類來(lái)處理這個(gè)邏輯
RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
return nil;
}];
RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber *num1 ,NSNumber *num2){
return [NSString stringWithFormat:@"%@ %@",num1,num2];
}];
[reduceSignal subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
ReactiveCocoa操作方法之秩序(控制流操作)鲫售。
doNext:
執(zhí)行Next之前,會(huì)先執(zhí)行這個(gè)Block
doCompleted:
執(zhí)行sendCompleted之前该肴,會(huì)先執(zhí)行這個(gè)Block
[[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
// 執(zhí)行[subscriber sendNext:@1];之前會(huì)調(diào)用這個(gè)Block
NSLog(@"doNext");;
}] doCompleted:^{
// 執(zhí)行[subscriber sendCompleted];之前會(huì)調(diào)用這個(gè)Block
NSLog(@"doCompleted");; }] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
ReactiveCocoa中的線程操作
deliverOn:
內(nèi)容傳遞切換到指定線程中情竹,副作用在原來(lái)線程中,把在創(chuàng)建信號(hào)時(shí)block中的代碼稱之為副作用。
subscribeOn:
內(nèi)容傳遞和副作用都會(huì)切換到指定線程中匀哄。
ReactiveCocoa操作方法之時(shí)間控制秦效。
timeout:
超時(shí)雏蛮,可以讓一個(gè)信號(hào)在一定的時(shí)間后,自動(dòng)報(bào)錯(cuò)阱州。
RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
return nil;
}] timeout:1 onScheduler:[RACScheduler currentScheduler]];
[signal subscribeNext:^(id x) {
NSLog(@"%@",x);
} error:^(NSError *error) {
// 1秒后會(huì)自動(dòng)調(diào)用
NSLog(@"%@",error);
}];
interval
定時(shí):每隔一段時(shí)間發(fā)出信號(hào)
[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
delay
延遲發(fā)送next挑秉。
RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
return nil;
}] delay:2] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
ReactiveCocoa操作方法之重復(fù)。
retry
重試 :只要失敗苔货,就會(huì)重新執(zhí)行創(chuàng)建信號(hào)中的block,直到成功.
throttle
節(jié)流:當(dāng)某個(gè)信號(hào)發(fā)送比較頻繁時(shí)犀概,可以使用節(jié)流,在某一段時(shí)間不發(fā)送信號(hào)內(nèi)容蒲赂,過(guò)了一段時(shí)間獲取信號(hào)的最新內(nèi)容發(fā)出阱冶。
RACSubject *signal = [RACSubject subject];
_signal = signal;
// 節(jié)流,在一定時(shí)間(1秒)內(nèi)滥嘴,不接收任何信號(hào)內(nèi)容木蹬,過(guò)了這個(gè)時(shí)間(1秒)獲取最后發(fā)送的信號(hào)內(nèi)容發(fā)出。
[[signal throttle:1] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];