ReactiveCocoa1

RACSignal

RAC中統(tǒng)一的數(shù)據(jù)接口,控件的事件杜漠,包括KVO勤家,timer都可以轉(zhuǎn)化成RACSignal抵卫。

創(chuàng)建:

1.RAC未控件的一部分原來的事件都通過Category的方式定義了event對應的signal,只需要直接拿來使用就好了抒巢。

2.自己創(chuàng)建

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))
didSubscribe;

? 3.訂閱

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

在信號創(chuàng)建的時候贫贝,需要傳入一個didSubscribe的block,在有其他訂閱者訂閱這個信號的時候,didSubscribe就會被調(diào)用稚晚,然后將數(shù)據(jù)通過subscribeNext的block傳入崇堵。

信號事件的種類

1.next,一般情況下客燕,信號處理業(yè)務邏輯正常返回的時候鸳劳,會調(diào)用訂閱者的sendNext方法將數(shù)據(jù)傳入訂閱者,訂閱者可以通過過subscribeNext獲取數(shù)據(jù)也搓。

2.error赏廓,有時候業(yè)務邏輯產(chǎn)生異常的時候,會調(diào)用訂閱者的sendError方法來告知訂閱者產(chǎn)生了異常傍妒,訂閱者在subscribeNext:erro:中處理異常錯誤幔摸。

3.completed,該事件表示訂閱者從信號中移除颤练,之后不再收到消息了既忆,信號生命周期結(jié)束。

創(chuàng)建一個請求賬號權(quán)限的信號

- (RACSignal *)requestAccessToTwitterSignal {
  
  // 1 - define an error
  NSError *accessError = [NSError errorWithDomain:RWTwitterInstantDomain
                                             code:
                                             RWTwitterInstantErrorAccessDenied
                                         userInfo:nil];
  
  // 2 - create the signal
  @weakify(self)
  return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    // 3 - request access to twitter
    @strongify(self)
    [self.accountStore
       requestAccessToAccountsWithType:self.twitterAccountType
         options:nil
      completion:^(BOOL granted, NSError *error) {
          // 4 - handle the response
          if (!granted) {
            [subscriber sendError:accessError];
          } else {
            [subscriber sendNext:nil];
            [subscriber sendCompleted];
          }
        }];
    return nil;
  }];
}

處理請求賬號權(quán)限的信號

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

信號的幾種操作

filter

將信號過濾嗦玖,只保留滿足block中條件的信號

只保留輸入字符串長度大于3的信號

[[self.usernameTextField.rac_textSignal
  filter:^BOOL(id value) {
    NSString *text = value;
    return text.length > 3;
  }]
  subscribeNext:^(id x) {
//這里只會顯示長度大于3的字符串
    NSLog(@"%@", x);
  }];

這里的信號先經(jīng)過filter過濾了一次患雇,再由subscribeNext得到過濾的信號進行處理,其數(shù)據(jù)流如下圖所示:

map

把源信號的值映射成一個新的值

[[[self.usernameTextField.rac_textSignal
  map:^id(NSString *text) {
    return @(text.length);
  }]
  filter:^BOOL(NSNumber *length) {
    return [length integerValue] > 3;
  }]
  subscribeNext:^(id x) {
    NSLog(@"%@", x);
  }];

信號先經(jīng)過map映射將字符串轉(zhuǎn)化成功了字符串長度的數(shù)據(jù)宇挫,再通過filter過濾掉了字符串長度等于3的信號苛吱,最后通過subscribeNext獲得最后符合條件的信號,整個過程包含了不同數(shù)據(jù)類型的變化捞稿,過程如下圖:

http://7xqgnx.com1.z0.glb.clouddn.com/RAC2.png

combineLatest

將多個信號合并起來又谋,每一個被合并的信號必須調(diào)用過一次sendNext,才能觸發(fā)合并的信號娱局,最后以元組的形式發(fā)出彰亥。

reduce

當信號發(fā)出的內(nèi)容是元組時,可以使用它將元組聚合成一個值衰齐。

將對姓名和密碼的驗證結(jié)果的兩種信合合并成一個信號任斋,再通過reduce返回最終是否驗證通過的信號。

RACSignal *signUpActiveSignal =
  [RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal]
                    reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid
                      ) {
                      return @([usernameValid boolValue] && [passwordValid 
                        boolValue]);
                    }];

數(shù)據(jù)流的狀態(tài):

doNext

在每次信號執(zhí)行訂閱者的Next方法之前耻涛,會調(diào)用這個方法废酷,它對信號本身不會產(chǎn)生影響。

在按鈕點擊之后抹缕,會有一系列驗證的過程澈蟆,在這期間,按鈕不能被再次點擊卓研,等待驗證結(jié)果出來之后趴俘,在恢復按鈕未正常使用的狀態(tài)睹簇。

 [[[[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];
     }
   }];

數(shù)據(jù)流的狀態(tài):

then

用于連接兩個信號,當?shù)谝粋€信號完成之后(前一個信號調(diào)用sendCompleted)寥闪,才會連接then返回的信號太惠,then之前的信號會被忽略

在得到否有權(quán)限獲得賬戶信息之后,通過then獲取搜索文本的信號疲憋,再驗證搜索文本的有效性凿渊,最后獲取有效的搜索文本。如果獲取賬號信息這一步出現(xiàn)錯誤缚柳,直接調(diào)用最后的error的block埃脏。

[[[[self requestAccessToTwitterSignal]
  then:^RACSignal *{
    @strongify(self)
    return self.searchText.rac_textSignal;
  }]
  filter:^BOOL(NSString *text) {
    @strongify(self)
    return [self isValidSearchText:text];
  }]
  subscribeNext:^(id x) {
    NSLog(@"%@", x);
  } error:^(NSError *error) {
    NSLog(@"An error occurred: %@", error);
  }];

數(shù)據(jù)流如下圖:

deliverOn

信號傳遞切換到指定線程中

現(xiàn)在創(chuàng)建一個信號在后臺線程下載一個圖片,可以考慮使用SDWebImage

-(RACSignal *)signalForLoadingImage:(NSString *)imageUrl {
  
  RACScheduler *scheduler = [RACScheduler
                         schedulerWithPriority:RACSchedulerPriorityBackground];
  
  return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber
    ) {
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]
    ];
    UIImage *image = [UIImage imageWithData:data];
    [subscriber sendNext:image];
    [subscriber sendCompleted];
    return nil;
  }] subscribeOn:scheduler];
}

圖片下載完成之后切換到主線程秋忙,設置圖片的顯示

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

throttle

節(jié)流剂癌,可以設置某一段時間內(nèi)不發(fā)送信號,等過了這段時間翰绊,將最新的信號發(fā)出

在用戶輸入搜索文字的時候,每一次textChange都會觸發(fā)搜索結(jié)果的網(wǎng)絡請求旁壮。請求次數(shù)過于頻繁且沒有必要监嗜,因為有時候可能是用戶還沒有輸完而已。并且結(jié)果頻繁的顯示清空體驗也不好÷招常現(xiàn)在通過throttle處理每經(jīng)過0.5秒處理一次搜索請求裁奇。

[[[[[[[self requestAccessToTwitterSignal]
  then:^RACSignal *{
    @strongify(self)
    return self.searchText.rac_textSignal;
  }]
  filter:^BOOL(NSString *text) {
    @strongify(self)
    return [self isValidSearchText:text];
  }]
  throttle:0.5]
  flattenMap:^RACStream *(NSString *text) {
    @strongify(self)
    return [self signalForSearchWithText:text];
  }]
  deliverOn:[RACScheduler mainThreadScheduler]]
  subscribeNext:^(NSDictionary *jsonSearchResult) {
    NSArray *statuses = jsonSearchResult[@"statuses"];
    NSArray *tweets = [statuses linq_select:^id(id tweet) {
      return [RWTweet tweetWithStatus:tweet];
    }];
    [self.resultsViewController displayTweets:tweets];
  } error:^(NSError *error) {
    NSLog(@"An error occurred: %@", error);
  }];

經(jīng)過最后的處理,數(shù)據(jù)流如下圖所示:

在requestAccessToTwitterSignal和signalForSearchWithText都有可能產(chǎn)生error麦撵,最后都會直接調(diào)用subscribleNext:error方法刽肠。

takeUnitl

(RACSignal *) 獲取信號直到某個信號執(zhí)行完成

比如,監(jiān)聽某個文本框的文本改變直到當前對象被銷毀

[_textField.rac_textSignal takeUntil:self.rac_willDeallocSignal];

skip

(NSUInteger) 跳過幾個信號免胃,選擇忽略不處理

第一次輸入不被監(jiān)聽

[[_textField.rac_textSignal skip:1] subscribeNext:^(id x) {
 
   NSLog(@"%@",x);
}];

常見的宏

RAC(object, property)

RAC(_titleLabel, text) = [viewModel.titleSignal takeUntil:self.
rac_prepareForReuseSignal];

表示將一個對象的屬性和一個signal進行綁定音五,signal每產(chǎn)生一個value,都會自動執(zhí)行如下代碼

[TARGET setValue:value ?: NIL_VALUE forKeyPath:KEYPATH]; 

RACObserve(TARGET, KEYPATH)

返回一個signal羔沙,檢測target的keypath屬性

RAC和RACObserve用在一起實現(xiàn)雙向綁定

RAC(self.outputLabel, text) = RACObserve(self.model, name);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載躺涝,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末扼雏,一起剝皮案震驚了整個濱河市坚嗜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诗充,老刑警劉巖苍蔬,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝴蜓,居然都是意外死亡碟绑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜈敢,“玉大人辜荠,你說我怎么就攤上這事∽ハ粒” “怎么了伯病?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長否过。 經(jīng)常有香客問我午笛,道長,這世上最難降的妖魔是什么苗桂? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任药磺,我火速辦了婚禮,結(jié)果婚禮上煤伟,老公的妹妹穿的比我還像新娘癌佩。我一直安慰自己,他們只是感情好便锨,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布围辙。 她就那樣靜靜地躺著,像睡著了一般放案。 火紅的嫁衣襯著肌膚如雪姚建。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天吱殉,我揣著相機與錄音掸冤,去河邊找鬼。 笑死友雳,一個胖子當著我的面吹牛稿湿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沥阱,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缎罢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了考杉?” 一聲冷哼從身側(cè)響起策精,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎崇棠,沒想到半個月后咽袜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡枕稀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年询刹,在試婚紗的時候發(fā)現(xiàn)自己被綠了谜嫉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡凹联,死狀恐怖沐兰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蔽挠,我是刑警寧澤住闯,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站澳淑,受9級特大地震影響比原,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜杠巡,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一量窘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧氢拥,春花似錦蚌铜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至出革,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渡讼,已是汗流浹背骂束。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留成箫,地道東北人展箱。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蹬昌,于是被迫代替她去往敵國和親混驰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

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