上篇RAC入門(mén)的文章相信大家都已經(jīng)比較了解了,下面就給大家介紹RAC比較高級(jí)的東西。
1.創(chuàng)建信號(hào)
// RACSignal使用步驟:
// 1.創(chuàng)建信號(hào) + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
// 2.訂閱信號(hào),才會(huì)激活信號(hào). - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
// 3.發(fā)送信號(hào) - (void)sendNext:(id)value
// RACSignal底層實(shí)現(xiàn):
// 1.創(chuàng)建信號(hào),首先把didSubscribe保存到信號(hào)中,還不會(huì)觸發(fā)。
// 2.當(dāng)信號(hào)被訂閱,也就是調(diào)用signal的subscribeNext:nextBlock
// 2.2 subscribeNext內(nèi)部會(huì)創(chuàng)建訂閱者subscriber,并且把nextBlock保存到subscriber中。
// 2.1 subscribeNext內(nèi)部會(huì)調(diào)用siganl的didSubscribe
// 3.siganl的didSubscribe中調(diào)用[subscriber sendNext:@1];
// 3.1 sendNext底層其實(shí)就是執(zhí)行subscriber的nextBlock
// 1.創(chuàng)建信號(hào)
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// block調(diào)用時(shí)刻:每當(dāng)有訂閱者訂閱信號(hào),就會(huì)調(diào)用block。
// 2.發(fā)送信號(hào)
[subscriber sendNext:@1];
// 如果不在發(fā)送數(shù)據(jù),最好發(fā)送信號(hào)完成,內(nèi)部會(huì)自動(dòng)調(diào)用[RACDisposable disposable]取消訂閱信號(hào)。
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// block調(diào)用時(shí)刻:當(dāng)信號(hào)發(fā)送完成或者發(fā)送錯(cuò)誤,就會(huì)自動(dòng)執(zhí)行這個(gè)block,取消訂閱信號(hào)。
// 執(zhí)行完Block后,當(dāng)前信號(hào)就不在被訂閱了。
NSLog(@"信號(hào)被銷毀");
}];
}];
// 3.訂閱信號(hào),才會(huì)激活信號(hào).
[siganl subscribeNext:^(id x) {
// block調(diào)用時(shí)刻:每當(dāng)有信號(hào)發(fā)出數(shù)據(jù),就會(huì)調(diào)用block.
NSLog(@"接收到數(shù)據(jù):%@",x);
}];
2.信號(hào)的處理:
filter:過(guò)濾前綴包含“mei”的字符串
[[mytextField.rac_textSignal filter:^BOOL(NSString *value) {
return [value hasPrefix:@"mei"];
}] subscribeNext:^(NSString *value) {
NSLog(@"This value has prefix `mei` : %@", value);
}];
ignore:忽略前綴包含“mei”的字符串
[[mytextField.rac_textSignal ignore:@"mei"] subscribeNext:^(NSString *value) {
NSLog(@"`mei` could never appear : %@", value);
}];
take:取前兩個(gè)
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}] take:2] subscribeNext:^(id x) {
NSLog(@"only 1 and 2 will be print: %@", x);
}];
skip:跳過(guò)第一個(gè)
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"1"];
[subscriber sendNext:@"2"];
[subscriber sendNext:@"3"];
[subscriber sendCompleted];
return nil;
}] skip:1] subscribeNext:^(id x) {
NSLog(@"only 2 and 3 will be print: %@", x);
}];
throttle:節(jié)流
可能大家還是不理解,我給大家舉個(gè)例子吧,我們公司曾經(jīng)有一個(gè)需求,當(dāng)用戶再輸入框輸入的文本發(fā)生改變的時(shí)候可以請(qǐng)求數(shù)據(jù),做到及時(shí)搜索的功能。就像百度現(xiàn)在的搜索體驗(yàn)。做到這個(gè)如果不考慮服務(wù)器壓力其實(shí)沒(méi)那么難,但是我們是追求完美的人,怎么能不考慮服務(wù)器性能呢。那么就有一個(gè)問(wèn)題,一旦輸入框發(fā)生改變我們就要從服務(wù)器獲取數(shù)據(jù)嗎,當(dāng)然不能這樣,這里我們?nèi)绻幸粋€(gè)時(shí)間延遲那就最好了,那就是節(jié)流。
這里再介紹一下switchToLatest,當(dāng)我們搜索的時(shí)候下一個(gè)搜索已經(jīng)開(kāi)始了可能上一個(gè)搜索還沒(méi)返回結(jié)果,我們就沒(méi)必要開(kāi)啟上一個(gè)搜索了,肯定是去最新的吧。所以switchToLatest就是這樣的一個(gè)功能。好了,下面就是兩者結(jié)合給我們的搜索優(yōu)化的一段代碼
[[[[[[textField.rac_textSignal throttle:0.3]distinctUntilChanged]ignore:@""] map:^id(id value) {
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// network request
[subscriber sendNext:value];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// cancel request
}];
}];
}]switchToLatest] subscribeNext:^(id x) {
NSLog(@"x = %@",x);
}];
repeat:重復(fù)
[[[[[RACSignal createSignal:^RACDisposable *(id subscriber) {
[subscriber sendNext:@"rac"];
[subscriber sendCompleted];
return nil;
}]delay:1]repeat]take:10] subscribeNext:^(id x) {
NSLog(@"x = %@",x);
} completed:^{
NSLog(@"完成");
}];
merge:合并 同時(shí)訂閱,各自執(zhí)行
RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"A");
[subscriber sendNext:@"a"];
[subscriber sendCompleted];
});
return nil;
}];
RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"B");
[subscriber sendNext:@"b"];
[subscriber sendCompleted];
});
return nil;
}];
[[RACSignal merge:@[signalA, signalB]]subscribeNext:^(id x) {
NSLog(@"x = %@",x);
}];
concat: 一個(gè)異步請(qǐng)求完成后,再啟動(dòng)另一個(gè)
RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"a");
[subscriber sendNext:@"a"];
[subscriber sendCompleted];
});
return nil;
}];
RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"b");
[subscriber sendNext:@"b"];
[subscriber sendCompleted];
});
return nil;
}];
[[signalA concat:signalB]subscribeNext:^(id x) {
NSLog(@"x=%@",x);
}];
zipWith:/combineLatest: 多個(gè)異步請(qǐng)求都完成后,再做某件事
RACSignal * signalA = [RACSignal createSignal:^RACDisposable *(id subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"a");
[subscriber sendNext:@"a"];
[subscriber sendCompleted];
});
return nil;
}];
RACSignal * signalB = [RACSignal createSignal:^RACDisposable *(id subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"b");
[subscriber sendNext:@"b"];
[subscriber sendCompleted];
});
return nil;
}];
[[signalA zipWith:signalB]subscribeNext:^(id x) {
NSLog(@"x = %@",x);
}];
RAC的一些宏
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:button];
button.frame = CGRectMake(100, 100, 180, 40);
RAC(button, backgroundColor) = [RACObserve(button, selected) map:^UIColor *(NSNumber * selected) {
return [selected boolValue] ? [UIColor redColor] : [UIColor greenColor];
}];
[[button rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(UIButton * btn) {
btn.selected = !btn.selected;
}];
RAC(showLabel, text) = mytextField.rac_textSignal;
RAC(showLabel, text) = [[[mytextField.rac_textSignal
startWith:@"不足3個(gè)字"] // startWith 一開(kāi)始返回的初始值
filter:^BOOL(NSString *value) { // filter使?jié)M足條件的值才能傳出
return value.length > 3;
}]map:^id(id value) {
// map將一個(gè)值轉(zhuǎn)化為另一個(gè)值輸出
return [value isEqualToString:@"meiqing"] ? @"驗(yàn)證成功!" : value;
}];
如果覺(jué)得文章還不錯(cuò),可以打賞哦。
微博賬號(hào):梅嘉慶(點(diǎn)擊關(guān)注)