记录一下RAC的使用
1 常规的对数组的操作,包括遍历、刷选、映射、替换
// 遍历
NSArray * array = @[@"1",@"2",@"3",@"4",@"5",@"6"]; [array.rac_sequence.signal subscribeNext:^(id _Nullable x) { NSLog(@"数组内容:%@", x); }];
注释:可遍历所有元素,但因为内部实现是异步执行的(for in是在当前线程),所以使用时候需要注意时间顺序。 // 刷选 NSArray *filter = [[array.rac_sequence filter:^BOOL(id value) { return [value integerValue] > 2; }] array]; NSLog(@"filter:%@",filter); // (3,4,5,6) // 映射 NSArray *map = [[array.rac_sequence map:^id(id value) { NSInteger a = [value integerValue] * [value integerValue]; return [NSString stringWithFormat:@"%ld", a]; }] array]; NSLog(@"map:%@",map); //(1,4,9,16,25,36)
// 数组替换所有元素
NSArray * array1 = @[@"1",@"2",@"3",@"4",@"5",@"6"];
NSArray * newArray = [[array1.rac_sequence mapReplace:@"99"] array];
NSLog(@"%@",newArray);
2 节流 throttle
表示 指定时间间隔内,不再发送信号 这里添加 throttle, 表示在 1 秒内 text 没有改变时,才会进行搜索请求
UITextField *textfield; [[[textfield rac_textSignal] throttle:1] subscribeNext:^(id x) { NSLog(@"开始搜索请求==%@", x); }];
3 事件处理 KVO监听 通知等
UITextField * textF; //实时监听输入框中文字的变化 [[textF rac_textSignal] subscribeNext:^(NSString * _Nullable x) { NSLog(@"输入框的内容--%@",x); }]; //UITextField的UIControlEventEditingChanged事件,免去了KVO [[textF rac_signalForControlEvents:UIControlEventEditingChanged] subscribeNext:^(__kindof UIControl * _Nullable x) { NSLog(@"%@",x); }]; //添加监听条件 [[textF.rac_textSignal filter:^BOOL(NSString * _Nullable value) { return [value isEqualToString:@"100"];//此处为判断条件,当输入的字符为100的时候执行下面方法 }]subscribeNext:^(NSString * _Nullable x) { NSLog(@"输入框的内容为%@",x); }]; UIButton *loginBtn; //监听点击事件 [[loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { NSLog(@"%@",x);//x为一个button对象,别看类型为UIControl,继承关系UIButton-->UIControl-->UIView-->UIResponder-->NSObject x.frame = CGRectMake(100, 210, 200, 300); }]; //KVO监听按钮frame的改变 [[loginBtn rac_valuesAndChangesForKeyPath:@"frame" options:(NSKeyValueObservingOptionNew) observer:self] subscribeNext:^(RACTwoTuple<id,NSDictionary *> * _Nullable x) { NSLog(@"frame改变了%@",x); }]; //定时器 [[RACSignal interval:2.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) { NSLog(@"你好哇。"); //这里面的方法2秒一循环 }]; //通知。。。不需要注销了 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) { NSLog(@"%@ 键盘弹起", x); // x 是通知对象 }];
4 反向传值,也可以使用block 代理 通知,但是使用RAC最简单
在controller中
SubView *subView = [[SubView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; subView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:subView]; [[subView rac_signalForSelector:@selector(sendValues:data:)] subscribeNext:^(RACTuple * _Nullable x) { NSLog(@"===111%@",x); }];
在SubView.h中声明这个方法
- (void)sendValues:(NSString *)type data:(NSDictionary *)dicc;
在SubView.m中调用这个方法
- (void)btnAction:(UIButton *)sender { [self sendValues:@"111" data:@{@"key" : @"values"}]; }
5 RACSubject使用
// 创建信号 RACSubject *subject = [[RACSubject alloc] init]; // 订阅信号 [subject subscribeNext:^(id _Nullable x) { NSLog(@"==%@",x); }]; // 发送信号 [subject sendNext:@"今天天气还是一如既往的好,希望明天也是如此"];
6 关于多请求的处理,其实可以使用GCD等方式,但是这里使用RAC还是比较方便的
- (void)demo7 { RACSignal *single1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { // 1:请求数据 // 2:发送数据 [subscriber sendNext:@"single1"]; return nil; }]; RACSignal *single2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { // 1:请求数据 // 2:发送数据 [subscriber sendNext:@"single2"]; return nil; }]; // 订阅信号 [single1 subscribeNext:^(id _Nullable x) { NSLog(@"------处理1..%@",x); }]; [single2 subscribeNext:^(id _Nullable x) { NSLog(@"------处理2。。%@",x); }]; // 当数组中所有信号都发送了数据,才会执行selector,必须带参,参数是sendNext发送过来的,必须和信号一一对应 // 参数:每个信号发送的数据,这里必须要带参数,不然会崩溃 [self rac_liftSelector:@selector(updateUIOneData:TwoData:) withSignalsFromArray:@[single1,single2]]; } - (void)updateUIOneData:(id)x1 TwoData:(id)x2 { NSLog(@"更新UI:%@----%@",x1,x2); }
7. 使用宏
UILabel *myLabel; // 监测某个对象的属性,发生变化时回直接回调给block [RACObserve(myLabel, text) subscribeNext:^(id _Nullable x) { NSLog(@"%@",x); }]; // RAC:把一个对象的某个属性绑定一个信号,只要发出信号,就会把信号的内容给对象的属性赋值 // 给label的text属性绑定了文本框改变的信号 UITextField *textfield; RAC(myLabel, text) = textfield.rac_textSignal; [textfield.rac_textSignal subscribeNext:^(id x) { myLabel.text = x; }];
举一个监听的例子。
需求就是监听scrollerview 的滑动。当滑动的时候就输出日志。如下:
UIScrollView *scrolView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 200, 400)]; scrolView.contentSize = CGSizeMake(200, 800); scrolView.backgroundColor = [UIColor greenColor]; [self.view addSubview:scrolView]; [RACObserve(scrolView, contentOffset) subscribeNext:^(id x) { NSLog(@"success"); }];
8. 补一下merge 和 combineLatest 的用法。
先看代码吧:
RACSubject *aaaaa = [RACSubject subject]; RACSubject *bbbbb = [RACSubject subject]; [[RACSignal merge:@[aaaaa,bbbbb]]subscribeNext:^(id x) { NSLog(@"信号发送combineLatest:%@",x); }]; [aaaaa sendNext:@"1000"]; [bbbbb sendNext:@"2000"];
和
RACSubject *aaaaa = [RACSubject subject]; RACSubject *bbbbb = [RACSubject subject]; [[RACSignal combineLatest:@[aaaaa,bbbbb]]subscribeNext:^(id x) { NSLog(@"信号发送combineLatest:%@",x); }]; [aaaaa sendNext:@"1000"]; [bbbbb sendNext:@"2000"];
这两个非常相似,merge指的是只要发送一个信号,block就会回掉,然后回调回来的是那个改变你的singal的值
而combineLatest也是只要发送一个信号,block就会回调,然后把所有信号的值以元祖的形式返回来
参考文章: https://www.jianshu.com/p/666bc733559a