ReactiveCocoa工具書

Context

反復接觸 ReactiveCocoa ,這次真的準備把它應用到實際開發(fā)中了.為了以后使用方便,這里列出一些常用關鍵字的使用方法,以備查詢.

常用方法

簡單訂閱 subscribeNext

使用場景:
“ 如果你改變了,讓我知道 “

[self.usernameTextField.rac_textSignal subscribeNext:^(id x) {
   NSLog(@"%@", x);
 }];

過濾條件 filter

使用場景:

“ 如果你改變了,并且滿足x條件, 那么再讓我知道 “

[[self.usernameTextField.rac_textSignal

    filter:^BOOL(id value) {
      NSString* text = value;
      return text.length > 4;
    }] subscribeNext:^(id x) {
  NSLog(@"%@", x);
}];

還有拆分的寫法,因為 block層級太深 ,可讀性不好:

RACSignal* usernameSourceSignal = self.usernameTextField.rac_textSignal;

RACSignal* filteredUsernameSignal =
    [usernameSourceSignal filter:^BOOL(id value) {
      NSString* text = value;
      return text.length > 3;
    }];

[filteredUsernameSignal subscribeNext:^(id x) {
  NSLog(@"%@", x);
}];

類型轉換 map

使用場景:

當需要從輸入信號中提取不同的信息時(比如這里, 從打印下個字符,到打印長度)

[[[self.usernameTextField.rac_textSignal
    map:^id(NSString* value) {
   return @(value.length);
 }] filter:^BOOL(NSNumber* value) {
   return [value integerValue] > 4;
 }] subscribeNext:^(id x) {
   NSLog(@"%@", x);
 }];
  • 注意: 可 map 的只能是對象

RAC 宏

使用場景: RAC(A,b)
利用信號改變 A 的 b 屬性值

// 驗證信號
RACSignal *validUsernameSignal =
 [self.usernameTextField.rac_textSignal
 map:^id(NSString *text) {
 return @([self isValidUsername:text]);
 }]; 

RAC(self.usernameTextField, backgroundColor) =
  [validUsernameSignal
    map:^id(NSNumber *passwordValid){
     return[passwordValid boolValue] ? [UIColor clearColor]:[UIColor yellowColor];
   }];

聚合信號 combineLatest

使用場景:
多個信號條件同時滿足, 才能產生有效信號(比如登陸的時候,用戶名有效并且密碼有效的時候,登陸按鈕才應該有效)

RACSignal *signUpActiveSignal =
  [
  RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal]
                    reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){
                      return @([usernameValid boolValue]&&[passwordValid boolValue]);
                    }
  ];
  • 使用combineLatest:reduce:方法把validUsernameSignal和validPasswordSignal產生的最新的值聚合在一起舔亭,并生成一個新的信號斜棚。每次這兩個源信號的任何一個產生新值時奇钞,reduce block都會執(zhí)行,block的返回值會發(fā)給下一個信號商叹。

事件信號

使用場景:
拿到UIKit控件的事件響應信號

[[self.signInButton
   rac_signalForControlEvents:UIControlEventTouchUpInside]
   subscribeNext:^(id x) {
     NSLog(@"button clicked");
   }];

封裝方法

使用場景:

想把一個異步的API 封裝成信號

- (RACSignal *)signInSignal {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber){
   [self.signInService 
     signInWithUsername:self.usernameTextField.text
               password:self.passwordTextField.text
               complete:^(BOOL success){
                    [subscriber sendNext:@(success)];
                    [subscriber sendCompleted];
     }];
   return nil;
}];
}

拿到信號中的信號 flattenMap

使用場景:

當需要從包含信號b的信號a中拿取信號b

[[[self.signInButton
   rac_signalForControlEvents:UIControlEventTouchUpInside]
   flattenMap:^id(id x){
     return[self signInSignal];
   }]
   subscribeNext:^(id x){
     NSLog(@"Sign in result: %@", x);
   }];

添加附加操作(Adding side-effects)

使用場景:
需要進行一些準備工作的時候

[[[[self.signInButton
   rac_signalForControlEvents:UIControlEventTouchUpInside]
   doNext:^(id x){
     self.signInButton.enabled =NO;
     self.signInFailureText.hidden =YES;
   }]
   flattenMap:^id(id x){
     return[self signInSignal];
   }]
   subscribeNext:^(NSNumber*signedIn){
     self.signInButton.enabled =YES;
     BOOL success =[signedIn boolValue];
     self.signInFailureText.hidden = success;
     if(success){
       [self performSegueWithIdentifier:@"signInSuccess" sender:self];
     }
   }];

移除訂閱 dispose

使用場景:

當需要手動釋放一個信號(當沒有訂閱,信號就不復存在),但是使用場景很少,僅供了解

RACSignal *backgroundColorSignal =
    [self.searchText.rac_textSignal 
        map:^id(NSString *text) { 
            return [self isValidSearchText:text] ? 
                [UIColor whiteColor] : [UIColor yellowColor]; 
    }]; 
    
RACDisposable *subscription = 
    [backgroundColorSignal 
        subscribeNext:^(UIColor *color) {
            self.searchText.backgroundColor = color; 
    }]; 
    
// at some point in the future ... 
[subscription dispose];

防止循環(huán)引用

@weakify(self) 
[[self.searchText.rac_textSignal 
    map:^id(NSString *text) { 
        return [self isValidSearchText:text] ? 
            [UIColor whiteColor] : [UIColor yellowColor]; 
    }] 
    subscribeNext:^(UIColor *color) { 
        @strongify(self) 
        self.searchText.backgroundColor = color; 
    }];

next error completed

在signal的生命周期中眯搭,它可能不發(fā)送事件结窘,發(fā)送一個或多個next事
件,在這之后還能發(fā)送一個completed事件或一個error事件失乾。

[[self requestAccessToTwitterSignal] 
    subscribeNext:^(id x) { 
        NSLog(@"Access granted"); 
    } error:^(NSError *error) { 
        NSLog(@"An error occurred: %@", error); 
    }];

信號鏈接 then

使用場景:
當后面的信號需要依賴前面的信號時

[[[self requestAccessToTwitterSignal] 
    then:^RACSignal *{ 
        @strongify(self) 
        return self.searchText.rac_textSignal; 
    }] 
    subscribeNext:^(id x) { 
        NSLog(@"%@", x); 
    } error:^(NSError *error) { 
        NSLog(@"An error occurred: %@", error); 
    }];
  • then方法會等待completed事件的發(fā)送常熙,然后再訂閱由then block返回的signal。這樣就高效地把控制權從一個signal傳遞給下一個仗扬。

  • then方法會跳過error事件症概,因此最終的subscribeNext:error: block還是會收到獲取訪問權限那一步發(fā)送的error事件。

異步信號

使用場景:
后臺加載資源

-(RACSignal *)signalForLoadingImage:(NSString *)imageUrl { 

    RACScheduler *scheduler = [RACScheduler 
        schedulerWithPriority:RACSchedulerPriorityBackground]; 
        
    return [[RACSignal createSignal:^RACDisposable *(id subscriber) { 
    
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]; 
        UIImage *image = [UIImage imageWithData:data]; 
    
    
        [subscriber sendNext:image]; 
        [subscriber sendCompleted]; 
        return nil; 
    }] subscribeOn:scheduler]; 
}
  • subscribeOn:來確保signal在指定的scheduler上執(zhí)行早芭。

在主線程上更新UI

cell.twitterAvatarView.image = nil; 
 
[[[self signalForLoadingImage:tweet.profileImageUrl] 
    deliverOn:[RACScheduler mainThreadScheduler]] 
    subscribeNext:^(UIImage *image) { 
        cell.twitterAvatarView.image = image; 
    }];

針對cell的重用問題, 有種更優(yōu)化的方法:

[[[[self signalForLoadingImage:tweet.profileImageUrl] 
    takeUntil:cell.rac_prepareForReuseSignal] 
    deliverOn:[RACScheduler mainThreadScheduler]] 
    subscribeNext:^(UIImage *image) { 
        cell.twitterAvatarView.image = image; 
    }];

延時響應 throttle

使用場景:

當用戶輸入完畢, 自定進行搜索的時候,不應該用戶每次改變輸入,都馬上搜索,應該當用戶停止輸入 x 秒之后,再進行搜索

@weakify(self);
[[self.passwordTextField.rac_textSignal throttle:2] subscribeNext:^(id x) {
  @strongify(self);
  self.hintLabel.text = (NSString*)x;
}];

參考網址:
http://www.raywenderlich.com/62699/reactivecocoa-tutorial-pt1
http://benbeng.leanote.com/post/ReactiveCocoaTutorial-part1

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末彼城,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子退个,更是在濱河造成了極大的恐慌募壕,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件语盈,死亡現場離奇詭異舱馅,居然都是意外死亡,警方通過查閱死者的電腦和手機刀荒,發(fā)現死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門代嗤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缠借,你說我怎么就攤上這事干毅。” “怎么了泼返?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵硝逢,是天一觀的道長。 經常有香客問我绅喉,道長渠鸽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任柴罐,我火速辦了婚禮徽缚,結果婚禮上,老公的妹妹穿的比我還像新娘革屠。我一直安慰自己凿试,他們只是感情好,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布屠阻。 她就那樣靜靜地躺著红省,像睡著了一般。 火紅的嫁衣襯著肌膚如雪国觉。 梳的紋絲不亂的頭發(fā)上吧恃,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音麻诀,去河邊找鬼痕寓。 笑死傲醉,一個胖子當著我的面吹牛,可吹牛的內容都是我干的呻率。 我是一名探鬼主播硬毕,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼礼仗!你這毒婦竟也來了吐咳?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤元践,失蹤者是張志新(化名)和其女友劉穎韭脊,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體单旁,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡沪羔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了象浑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔫饰。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖愉豺,靈堂內的尸體忽然破棺而出篓吁,到底是詐尸還是另有隱情,我是刑警寧澤粒氧,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布越除,位于F島的核電站节腐,受9級特大地震影響外盯,放射性物質發(fā)生泄漏。R本人自食惡果不足惜翼雀,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一饱苟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狼渊,春花似錦箱熬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至米苹,卻和暖如春糕伐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蘸嘶。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工良瞧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留陪汽,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓褥蚯,卻偏偏與公主長得像挚冤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赞庶,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容