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 *(idsubscriber) { [subscriber sendCompleted]; return nil; }] delay:1] //延時一秒 subscribeCompleted:^{ @strongify(self); doRequest(); self.loadingDispose = nil; }]; }
[self.loadingDispose dispose]; RACSignal *loggingSignal = [RACSignal createSignal:^ RACDisposable * (idsubscriber) {//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