五月份的时候研究过一段时间RAC,后来因为换了新工作,公司的事情挺多,这段时间公司的事情少点了,又从新拾起了RAC的学习,已经看了很多的别人的博客,里面的东西也都是从别人的博客偷得,现在把我总结的一些东西,写出来.
开始!
.
0. 监听协议方法被触发
[[self rac_signalForSelector:@selector(tableView:didSelectRowAtIndexPath:) fromProtocol:@protocol(UITableViewDelegate)] subscribeNext:^(id x) {
}];
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:@"test" object:nil] subscribeNext:^(id x) {
}];
3.concat 信号连接
RACSignal *signalA;
RACSignal *signalB;
[signalA concat:signalB] subscribeNext:^(id x){
NSLog(@“%@“,x);
}
signalA相当于皇帝,signalB相当于太子,只要皇帝没有sendcompleted,太子就不能发号命令
4.merge 信号合并,合并多个信号,只要任何一个信号有了输出,结合体就有输出
RACSignal *signalA;
RACSignal *signalB;
[signalA merge:signalB] subscribeNext:^(id x){
NSLog(@“%@“,x);
}
A或者B有了新信号都会输出
5. combineLatest 信号组合
[[signalA combineLatest:signalB] subscribeNext:^(RACTuple* x){
RACTupleUnpack(NSSTring *stringA,NSString *stringB) = x;
NSLog(@“%@ %@“,stirngA,stringB);
}
RACSignal *signalA; 输出 A_1 A_2
RACSignal *signalB; 输出 B_1
最终结果 A_2 B_1
合并体输出的值是各个信号的最新输出值
6. zipWith 压缩(不知道有没有更好的翻译)
RACSignal *signalA; 输出 A_1 A_2
RACSignal *signalB; 输出 B_1 B_2
最终输出: A_1 B_1 A_2 B_2
[signalA zipWith:signalB subscribeNext:^(RACTuple* x){
RACTupleUnpack(NSSTring *stringA,stringB);
}
当A和B都有了新值的时候才输出,输出的是一个结合体 RACTuple 需要只用TupleUnPack进行分解,有个把这个方法比作成了夫妻,夫妻两个共同输入密码才能打开密码箱,其中一个人completed,夫妻就解散了.
7. map 映射(转换,转型 (大概意思吧))
[signal map:^id(id value){
if([value isEqualToString:@“石”]){
Return @“金”;
}]
点石成金,好方法
8. filter 过滤
[signal filter:^BOOL(id value){
return [value intvalue]>3;
}]
符合条件的才允许通过
9. flattenMap 过滤 返回的是一个信号 但是没有发现好的解释,以后更新
10. then then方法会等completed事件发出后调用(具体有什么实际用处暂未发现)
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"test- then"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(5 * NSEC_PER_SEC)),dispatch_get_main_queue(),^{
[subscriber sendCompleted];
});
return nil;
}]
then:^RACSignal *{
NSLog(@"then-Action");
return nil;
}]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
过了五秒,会输出 then-Action
11. delay 延迟输出
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"hello world"];
return nil;
}] delay:5]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
.
12. replay 重放
__block int aNumber = 0;
RACSignal *asignal = [[RACSignal createSignal:^RACDisposable *
(id<RACSubscriber> subscriber) {
aNumber++;
[subscriber sendNext:@(aNumber)];
[subscriber sendCompleted];
return nil;
}] replay];
[asignal subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
[asignal subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
输入 1 1
如果不加replay 输出1 2
可以防止side effect(副作用,不知道有没有更好的方法) 保证signal只被触发一次,然后把sendNext的value存起来,下次再subscribe时,直接发送缓存数据
13. intervel 定时
[RACSignal intervel:1.0f onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x){ NSLog(@“你该吃药"); }
每隔一秒输出一次
14. retry 重试
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
if (index <10) {
index ++;
NSLog(@"失败");
[subscriber sendError:nil];
}
else{
NSLog(@"我成功了");
[subscriber sendNext:nil];
}
return nil;
}] retry] subscribeNext:^(id x) {
NSLog(@"终于成功");
}];
一直尝试,直到输出不是error
15. throttle:time 节流 在一定的时长,只能通过一个信号,如果在这个时间内有其他的操作,需要等待time时长
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACSignal interval:2 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) { index++; [subscriber sendNext:[NSString stringWithFormat:@"%d",index]];
}];
return nil;
}]throttle:1]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
在一秒内只能输出一个信号,我设置的每隔两秒输出一次,如果把throttle:时间比定时的时间长,永远也不会subscribeNext
16. takeUntil:signalA 直到接收到这个信号,才停止subscribeNext
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACSignal interval:1.0f onScheduler:[RACScheduler mainThreadScheduler]]
subscribeNext:^(id x) {
[subscriber sendNext:@"直到世界尽头才能把我们分开"];
}];
return nil;
}] takeUntil:[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,^{
NSLog(@"世界尽头到了");
[subscriber sendNext:@"世界尽头到了"];
});
return nil;
}]] subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
传言这个takeUntil用的好的地方还是cell中btn 的复用,防止btn每次复用时,btn都会被addTarget:selector;
[[[cell.detailBtn race_signalForcontrolEvents:UIControlEventTouchUpInside] takeUntil:celeriac_prepareForReuseSignal]
subscribeNext:^(id x){ }];
17 UIView CateGories 文档里面有各种view,这里讲一下,我最喜欢用的一个view
UIAlertView *alter = [[UIAlertView alloc]initWithTitle:@"温馨提示" message:@"alter" delegate:nil cancelButtonTitle:@"确定"otherButtonTitles:@"取消",nil];
[alter show];
[[alter rac_buttonClickedSignal] subscribeNext:^(id x) { NSLog(@"subscribeNext:%@",x);
}];
太棒了,真心喜欢这么用,
18. NSObject CateGories
18.1 rac_willDealllocSignal 对象即将被摧毁的时候调用
NSArray *array = @[@“foo"]; [array rac_willDealllocSignal] subscribeCompleted:^{ nslog(@“oops");
}];
array = nil;
不知道这段代码没有执行,正在寻找问题
18.2 rac_liftSelector:@select(methods)withSignals:signalA,signalB 绑定两个信号,只要两个信号都有输出值,才会触发methods方法,接下来只有任何一个signal有了新的值,都会自动触发
[subscriber sendNext:@"C"];
double delayInSeconds = 2.0;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(delayInSeconds * NSEC_PER_SEC)),^{
[subscriber sendNext:@"A"];
});
return nil;
}];
RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@"B"];
// [subscriber sendNext:@"C"];
return nil;
}];
- (void)doA:(NSString *)A withB:(NSString*)B{
NSLog(@"A:%@ B:%@",A,B);
}
输出
A:C B:B
A:A B:B
- 只要有RACObserve的地方都有使用 weakify/strongify 消除循环引用
- ignore:(id) 忽略给定的值
[[self.inputTextField.rac_textSignal ignore:@"su"] subscribeNext:^(NSString *value) {
NSLog(@"`sunny` could never appear : %@",value);
}];
暂时还没有发现怎么好用,比如上面 我过滤的是 su 输入s 输出s 输入 u 不输出,输入s 输出sus
21. ignoreValues 忽略所有值,只关心signal结束,只取complete和error两个消息
22. distinctUntilChanged 将这次的值和上次的值作比较,如果相同则忽略
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]]subscribeNext:^(id x) { [subscriber sendNext:[NSString stringWithFormat:@"%d",index]];
}];
return nil;
}] distinctUntilChanged] subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
只会输出0
23. take: 从开始取N次的next的值,不包括completion和error
__block int index = 0;
[[[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] take:5] subscribeNext:^(id x) {
index ++;
NSLog(@"index:%d",index);
}];
输出: 1 2 3 4 5
24,takeLast: 取最后的N次next的值,等待error 或者completion之后输出.
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) { index++; [subscriber sendNext:[NSString stringWithFormat:@"%d",index]];
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,^{
[subscriber sendCompleted];
});
return nil;
}]
takeLast:3]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
输出 3 4 5
25,takeUntil: signal 在接受到某个信号之前,一直取值,直到接收到这个信号,不再取值
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) { index++; [subscriber sendNext:[NSString stringWithFormat:@"%d",index]];
}];
return nil;
}]
takeUntil:[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,^{
[subscriber sendCompleted];
});
return nil;
}]]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
输出 1,2,3,4
26 skip:N 从开始跳过N次的next值
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) { index++; [subscriber sendNext:[NSString stringWithFormat:@"%d",index]];
}];
return nil;
}]
skip:3]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
输出: 4 5 6 ……
27 skipUntilBlock 一直跳等到block输出为yes,才有输出值
__block int index = 0;
[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) { [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(id x) { index++; [subscriber sendNext:[NSString stringWithFormat:@"%d",index]];
}];
return nil;
}]
skipUntilBlock:^BOOL(id x) {
NSString *str = [NSString stringWithFormat:@"%@",x];
return [str intValue]>3;
}]
subscribeNext:^(id x) {
NSLog(@"x:%@",x);
}];
输出 4 5 6….. 28 skipWhileBlock 和skipUntilBlock 的区别 感觉像是 while do 和 do while的区别