1、ReactiveCocoa開發中常見用法
-
代替代理:
rac_signalForSelector:用于替代代理。
-
代替KVO :
rac_valuesAndChangesForKeyPath:用于監聽某個對象的屬性改變。
-
監聽事件:
rac_signalForControlEvents:用于監聽某個事件。
-
代替通知:
rac_addObserverForName:用于監聽某個通知。
-
監聽文本框文字改變:
rac_textSignal:只要文本框發出改變就會發出這個信號。
2、ReactiveCocoa高級用法
-
Map
Map作用:把源信號的值映射成一個新的值
###### Map使用步驟:
1.傳入一個block,類型是返回對象,參數是value
2.value就是源信號的內容,直接拿到源信號的內容做處理
3.把處理好的內容,直接返回就好了,不用包裝成信號,返回的值,就是映射的值。
Map使用場景:
1.服務端返回的數據不是你需要的,需要進行一次二次加工,使用 map就會很方便
[[_textField.rac_textSignal map:^id(id value) {
// 當源信號發出,就會調用這個block,修改源信號的內容
// 返回值:就是處理完源信號的內容。
return [NSString stringWithFormat:@"輸出:%@",value];
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
concat
concat:按一定順序拼接信號,當多個信號發出的時候,有順序的接收信號。
concat使用場景:
1.在工作中,有這樣的需求,可能一個頁面要發送幾個API,要求有一個API是依賴其他幾個API,等到所有API都成功之后在刷新UI
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal3 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}];
//信號3依賴信號1和信號2
RACSignal *signal = [[[RACSignal merge:@[signal1,signal2]]concat:signal3] filter:^BOOL(id value) {
return [value isKindOfClass:[NSNumber class]];
}];
[signal subscribeNext:^(id x) {
NSLog(@"====%@",x);
}completed:^{
NSLog(@"所有都完事了");
}];
log
2017-03-07 17:25:35.339 racDemo[61024:1544009] ====1
2017-03-07 17:25:35.340 racDemo[61024:1544009] ====2
2017-03-07 17:25:35.341 racDemo[61024:1544009] 所有都完事了
記得加 [subscriber sendCompleted];
-
Zip
zip:把兩個信號壓縮成一個信號,只有當兩個信號同時發出信號內容時,并且把兩個信號的內容合并成一個元組,才會觸發壓縮流的next事件。
RACSignal *signal1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal3 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}];
RACSignal *signal = [RACSignal zip:@[signal1,signal2,signal3] reduce:^id(NSNumber *s1,NSNumber *s2,NSString *s3){
return RACTuplePack(s1,s2,s3);
}];
[signal subscribeNext:^(RACTuple *tuple) {
RACTupleUnpack(NSNumber *num1,NSNumber *num2,NSString *s3) = tuple;
NSLog(@"%@%@%@",num1,num2,s3);
}completed:^{
NSLog(@"所有都完事了");
}];
log
2017-03-07 17:38:57.227 racDemo[61197:1553408] 123
2017-03-07 17:38:57.227 racDemo[61197:1553408] 所有都完事了
tips:
1,記住要發送 [subscriber sendCompleted];
2,順序不要亂了,每一個信號對應一個返回,順序錯了,返回的值也就不對應了
3,sendNext只會走一次,如果有兩個sendNext,那么第二個發過來的值就不會生效
4,如果只要一個值,就沒有必要RACTuplePack了
eg:
[subscriber sendNext:@"3"];
[subscriber sendNext:@"100"];
[subscriber sendCompleted];
同樣代碼,在后面多加上一個sendNext 輸出結果如下
2017-03-07 17:44:17.808 racDemo[61350:1558976] 123
2017-03-07 17:44:17.808 racDemo[61350:1558976] 所有都完事了
-
combineLatest:
combineLatest將多個信號合并起來,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext,才會觸發合并的信號。
RACSignal combineLatest:<#(id<NSFastEnumeration>)#> reduce:<#^id(void)reduceBlock#>
RACSignal combineLatest:<#(id<NSFastEnumeration>)#>
用法和zip reduce差不多,但是每次有最新的都會回調
-
filter:
// 過濾:
// 每次信號發出,會先執行過濾條件判斷.
[_textField.rac_textSignal filter:^BOOL(NSString *value) {
return value.length > 3;
}];
-
doNext && doCompleted
[[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] doNext:^(id x) {
// 執行[subscriber sendNext:@1];之前會調用這個Block
NSLog(@"doNext");;
}] doCompleted:^{
// 執行[subscriber sendCompleted];之前會調用這個Block
NSLog(@"doCompleted");;
}] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
interval
[[RACSignal interval:1 onScheduler:[RACScheduler currentScheduler]] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
-
then
then:用于連接兩個信號,當第一個信號完成,才會連接then返回的信號。
// then:用于連接兩個信號,當第一個信號完成,才會連接then返回的信號
// 注意使用then,之前信號的值會被忽略掉.
// 底層實現:1、先過濾掉之前的信號發出的值。2.使用concat連接then返回的信號
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendCompleted];
return nil;
}] then:^RACSignal *{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@2];
return nil;
}];
}] subscribeNext:^(id x) {
// 只能接收到第二個信號的值,也就是then返回信號的值
NSLog(@"%@",x);
}];