ReactiveCocoa學(xué)習(xí)之路

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ò)濾和組合.

參考博文:

MVVM+RAC英文教程

http://www.reibang.com/p/87ef6720a096

http://www.cocoachina.com/ios/20150123/10994.html

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)分別為:nexterror拥诡、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):

  1. signalBlock必須要返回一個(gè)信號(hào)食零,不能傳nil.
  2. 如果不想要傳遞信號(hào)困乒,直接創(chuàng)建空的信號(hào)[RACSignal empty];
  3. RACCommand中信號(hào)如果數(shù)據(jù)傳遞完,必須調(diào)用[subscriber sendCompleted]贰谣,這時(shí)命令才會(huì)執(zhí)行完畢娜搂,否則永遠(yuǎn)處于執(zhí)行中。
  4. 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);
}];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末若皱,一起剝皮案震驚了整個(gè)濱河市镊叁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌走触,老刑警劉巖晦譬,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異互广,居然都是意外死亡敛腌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門惫皱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)像樊,“玉大人,你說(shuō)我怎么就攤上這事旅敷∩鳎” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵媳谁,是天一觀的道長(zhǎng)涂滴。 經(jīng)常有香客問(wèn)我,道長(zhǎng)晴音,這世上最難降的妖魔是什么柔纵? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮锤躁,結(jié)果婚禮上首量,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好加缘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布鸭叙。 她就那樣靜靜地躺著,像睡著了一般拣宏。 火紅的嫁衣襯著肌膚如雪沈贝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天勋乾,我揣著相機(jī)與錄音宋下,去河邊找鬼。 笑死辑莫,一個(gè)胖子當(dāng)著我的面吹牛学歧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播各吨,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼枝笨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了揭蜒?” 一聲冷哼從身側(cè)響起横浑,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屉更,沒(méi)想到半個(gè)月后徙融,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瑰谜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年欺冀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萨脑。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡隐轩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砚哗,到底是詐尸還是另有隱情龙助,我是刑警寧澤砰奕,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布蛛芥,位于F島的核電站,受9級(jí)特大地震影響军援,放射性物質(zhì)發(fā)生泄漏仅淑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一胸哥、第九天 我趴在偏房一處隱蔽的房頂上張望涯竟。 院中可真熱鬧,春花似錦、人聲如沸庐船。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)筐钟。三九已至揩瞪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間篓冲,已是汗流浹背李破。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壹将,地道東北人嗤攻。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像诽俯,于是被迫代替她去往敵國(guó)和親妇菱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容