ReactiveCocoa是響應式編程(FRP)在IOS中的一個實現框架,它的開源地址為:https://github.com/ReactiveCocoa/ReactiveCocoa# ;在網上看了幾篇文章,感覺理論講了很多,但是代碼還是看不太懂,於是自己把它github文檔上的一些使用的經典示例實現了一下,項目中有需要時可以直接搬過去用,用的熟練了再讀源碼也比較容易理解。
例1. 監聽對象的成員變量變化,當成員變量值被改變時,觸發做一些事情。
這種情況其實就是IOS KVO機制使用的場景,使用KVO實現,通常有三個步驟:1,給對象的成員變量添加監聽;2,實現監聽回調;3,取消監聽;而通過RAC可以直接實現,RAC的回調是通過block實現的,類似於過程式編程,上下文也更容易理解一些。
場景:當前類有一個成員變量 NSString *input,當它的值被改變時,發送一個請求。
實現:
[RACObserve(self, input)
subscribeNext:^(NSString* x){
request(x);//發送一個請求
}];每次input值被修改時,就會調用此block,並且把修改後的值做為參數傳進來。
場景:在上面場景中,當用戶輸入的值以2開頭時,才發請求.
實現:
[[RACObserve(self, input)
filter:^(NSString* value){
if ([value hasPrefix:@"2"]) {
return YES;
} else {
return NO;
}
}]
subscribeNext:^(NSString* x){
request(x);//發送一個請求
}];實現:
[[self.priceInput.rac_textSignal
filter:^(NSString *str) {
if (str.integerValue > 20) {
return YES;
} else {
return NO;
}
}]
subscribeNext:^(NSString *str) {
request(x);//發送一個請求 }];
例2. 同時監聽多個變量變化,當這些變量滿足一定條件時,使button為可點擊狀態
場景:button監聽 兩個輸入框有值和一個成員變量值,當輸入框有輸入且成員變量為真時,button為可點擊狀態
實現:
RAC(self.payButton,enabled) = [RACSignal
combineLatest:@[self.priceInput.rac_textSignal,
self.nameInput.rac_textSignal,
RACObserve(self, isConnected)
]
reduce:^(NSString *price, NSString *name, NSNumber *connect){
return @(price.length > 0 && name.length > 0 && [connect boolValue]);
}];場景:滿足上面條件時,直接發送請求
實現:
[[RACSignal
combineLatest:@[self.priceInput.rac_textSignal,
self.nameInput.rac_textSignal,
RACObserve(self, isConnected)
]
reduce:^(NSString *price, NSString *name, NSNumber *connect){
return @(price.length > 0 && name.length > 0 && ![connect boolValue]);
}]
subscribeNext:^(NSNumber *res){
if ([res boolValue]) {
NSLog(@"XXXXX send request");
}
}];例3. 類似於生成產-消費
場景:用戶每次在TextField中輸入一個字符,1秒內沒有其它輸入時,去發一個請求。TextField中字符改變觸發事件已在例1中展示,這裡實現一下它觸法的方法,把1秒延時在此方法中實現。
實現:
- (void)showLoading {
[self.loadingDispose dispose];//上次信號還沒處理,取消它(距離上次生成還不到1秒)
@weakify(self);
self.loadingDispose = [[[RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendCompleted];
return nil;
}] delay:1] //延時一秒
subscribeCompleted:^{
@strongify(self);
doRequest();
self.loadingDispose = nil;
}];
} [self.loadingDispose dispose];
RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (id subscriber) {//BLOCK_1
subscriptions++;
[subscriber sendNext:@"mytest"];
[subscriber sendCompleted];
return nil;
}];
loggingSignal = [loggingSignal delay:10];
self.loadingDispose = [loggingSignal subscribeNext:^(NSString* x){//BLOCK_2
NSLog(@"%@",x);
NSLog(@"subscription %u", subscriptions);
}];
self.loadingDispose = [loggingSignal subscribeCompleted:^{//BLOCK_3
NSLog(@"subscription %u", subscriptions);
}];
loggingSignal在每次被調用subscriibeNext:^(id x)或subscribeCompleted:^方法時(12行和17行),它創建進傳進的參數block_1就會被觸動發,而block_1中的sendNext:方法會調用subscriibeNext:^中對應的block_2, 而block_1中的sendCompleted會調用subscribeCompleted:中對應的block_3