前言
RAC
全称 ReactiveCocoa
,是一个重量级的三方框架,接管了苹果的所有事件机制,RAC主要是 监听事件
,并能 立即作为响应
,即 响应式编程
。
RAC 大纲
RAC信号三部曲
1 2 3 4
| // 创建信号 RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { return nil; }];
|
注:
在创建信号中有个block参数 subscriber(订阅者),只有在接收到订阅信号时,才能发送信号
1 2 3 4
| // 订阅信号 [signal subscribeNext:^(id _Nullable x) { ZJLog(@"x:%@",x); }];
|
注:
订阅信号通过block接收发送信号的内容
1 2
| // 发送信号 [subscriber sendNext:@"test"];
|
注:
发送信号,要放在创建信号的block中
1 2 3 4 5 6 7 8 9
| // 创建信号 [[RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { // 发送信号 [subscriber sendNext:@"This is RAC"]; return nil; }] subscribeNext:^(id _Nullable x) { // 订阅信号 NSLog(@"x:%@",x); }];
|
RAC的使用
1 2 3
| [[self.dynamicBtn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { NSLog(@"x:%@",x); }];
|
1 2 3 4
| // 监听密码改变的状态 [[self.pwdTF rac_textSignal] subscribeNext:^(NSString * _Nullable x) { [weakSelf handlePwdChangeAction:x]; }];
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| [[RACSignal combineLatest:@[self.oldpwdTF.rac_textSignal, self.newpwdTF.rac_textSignal, self.surepwdTF.rac_textSignal] reduce:^id _Nonnull(NSString * oldpwd,NSString * newpwd,NSString * surepwd){ // NSLog(@"%@--%@--%@",oldpwd,newpwd,surepwd); // 返回 return @(oldpwd.length >= 6 && newpwd.length >= 6 && surepwd.length >= 6); }] subscribeNext:^(id _Nullable x) { // ZJLog(@"%@",x); // 是否能够点击 BOOL isEnabled = [x boolValue]; weakSelf.finishBtn.enabled = isEnabled; if (isEnabled) { weakSelf.finishBtn.backgroundColor = kColorHexStrA(@"#3161F3", 1.0); }else { weakSelf.finishBtn.backgroundColor = kColorHexStrA(@"#3161F3", 0.3); } }];
|
1 2 3 4
| // 监听将要进入前台 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationWillEnterForegroundNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) { ZJLog(@"将要进入前台"); }];
|
1 2 3 4 5 6 7 8 9 10
| @property(noatomic,assign) int age;
[[self rac_valueForKeyPath:@"age" observer:nil] subscribeNext:^(id x ){ NSLog(@"%@",x); }];
// 模拟一个事件 触摸屏幕 就让age自增 -(void)touchesBegin:(NSSet<UITouch*>*)touches WithEvent:(UIEvent*)event{ age++; }
|
1 2 3 4
| // 监听当前视图控制器 中心圆点的变化 [RACObserve(self.view, center) subscribeNext:^(id _Nullable x) { NSLog(@"x:%@",x); }];
|
RAC实现读个网络请求都完成后再刷新界面
使用方法 - (RACSignal *)rac_liftSelector:(SEL)selector withSignalsFromArray:(NSArray *)signals
当传入的 signals
(信号数组),每一个 signal 都至少 sendNext 过一次,才会去触发第一个 selector 参数的方法,就是说放 signals 中的所有请求信号都执行完成后才会触发 selector 对应的方法
应用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"请求第一项数据"); [subscriber sendNext:@"获取到第一项数据"]; return nil; }]; RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"请求第二项数据"); [subscriber sendNext:@"获取到第二项数据"]; return nil; }]; RACSignal * signal3 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"请求第三项数据"); [subscriber sendNext:@"获取到第三项数据"]; return nil; }]; /* Selector 调用:当所有信号都发送数据时调用 数组存放多个信号 Selector 注意点:参数根据数组元素决定(数据的顺序/数据类型) Selector 方法中的参数类型,就是信号传递出来的数据 */ [self rac_liftSelector:@selector(updateUIWithData1:data2:data3:) withSignalsFromArray:@[signal1,signal2,signal3]]; }
- (void)updateUIWithData1:(NSString *)data1 data2:(NSString *)data2 data3:(NSString *)data3{ // 输出 data1:获取到第一项数据 data2:获取到第三项数据 data3:获取到第二项数据 NSLog(@"data1:%@ data2:%@ data3:%@",data1,data2,data3); }
|
concat (网络请求的顺序执行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"请求A数据"); [subscriber sendNext:@"A"]; // 发送信号完成,表示不再订阅了,内部会自动调用[RACDisposable disposable]取消订阅信号。 [subscriber sendCompleted]; return nil; }]; RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"请求B数据"); [subscriber sendNext:@"B"]; [subscriber sendCompleted]; return nil; }]; RACSignal * signal3 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"请求C数据"); [subscriber sendNext:@"C"]; [subscriber sendCompleted]; return nil; }]; // 按顺序执行信号 RACSignal * concatSignal = [RACSignal concat:@[signal1,signal2,signal3]]; [concatSignal subscribeNext:^(id _Nullable x) { // 分别输出A,B,C NSLog(@"%@",x); }];
|
查看打印结果:
1 2 3 4 5 6
| 2023-07-15 16:29:01.411929+0800 DigitalGuard[11168:862724] 请求A数据 2023-07-15 16:29:05.033538+0800 DigitalGuard[11168:862724] A 2023-07-15 16:29:05.035488+0800 DigitalGuard[11168:862724] 请求B数据 2023-07-15 16:29:08.084930+0800 DigitalGuard[11168:862724] B 2023-07-15 16:29:08.085394+0800 DigitalGuard[11168:862724] 请求C数据 2023-07-15 16:29:09.900995+0800 DigitalGuard[11168:862724] C
|
merge 合并信号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@"1"]; return nil; }]; RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@"2"]; return nil; }]; RACSignal * signal3 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@"3"]; return nil; }];
RACSignal * mergeSignal = [RACSignal merge:@[signal3,signal1,signal2]]; [mergeSignal subscribeNext:^(id _Nullable x) { // 分别输出3,1,2 NSLog(@"x:%@",x); }];
|
then
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@(1)]; [subscriber sendCompleted]; return nil; }]; RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@(2)]; [subscriber sendCompleted]; return nil; }]; RACSignal * thenSignal = [signal1 then:^RACSignal * _Nonnull{ return signal2; }]; [thenSignal subscribeNext:^(id _Nullable x) { // 输出2 NSLog(@"%@",x); }];
|
zip
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@(1)]; // 不会覆盖上一个信号 [subscriber sendNext:@(3)]; return nil; }]; RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { [subscriber sendNext:@(2)]; return nil; }] ; RACSignal *zipSignal = [RACSignal zip:@[signal1,signal2]]; [zipSignal subscribeNext:^(id _Nullable x) { // 输出(1,2) NSLog(@"%@",x); }];
|
常用宏
- RAC(TARGET,…) : 给某个对象的某个属性进行绑定
1 2
| // 当textfield开始编辑时,关闭button响应 RAC(_button,enabled) = [[self rac_signalForSelector:@selector(textFieldDidBeginEditing:) fromProtocol:@protocol(UITextFieldDelegate)] mapReplace:@NO];
|
- RACObserve(TARGET, KEYPATH):KVO,监听某个对象的属性,返回的是信号
1 2 3 4
| [RACObserve(self.view, backgroundColor) subscribeNext:^(id _Nullable x) { // 新背景颜色 NSLog(@"%@",x); }];
|
- RACChannelTo:用于双向绑定的一个通道终端
1 2
| // 将 button.backgroundColor 跟 view.backgroundColor 绑定 RACChannelTo(button,backgroundColor) = RACChannelTo(view,backgroundColor);
|
combineLatest
1 2 3 4 5 6 7 8 9
| // 创建信号A RACSubject * signalA = [RACSubject subject]; // 创建信号B RACSubject * signalB = [RACSubject subject]; [[RACSignal combineLatest:@[signalA,signalB]]subscribeNext:^(RACTuple * _Nullable x) { NSLog(@"%@",x); }]; [signalA sendNext:@"A"]; [signalB sendNext:@"B"];
|
reduce聚合
- 把信号发出元组的值聚合成一个值,可以把数据处理完成返回一个新的值
1 2 3 4 5 6 7 8 9 10 11 12 13
| // 创建信号A RACSubject * signalA = [RACSubject subject]; // 创建信号B RACSubject * signalB = [RACSubject subject]; [[RACSignal combineLatest:@[signalA,signalB] reduce:^id _Nullable(NSString *username,NSString *pwd){ // 处理数据 return [NSString stringWithFormat:@"reduce--%@--%@",username,pwd]; }]subscribeNext:^(id _Nullable x) { // 输出 reduce--A--B NSLog(@"reduce--%@",x); }]; [signalA sendNext:@"A"]; [signalB sendNext:@"B"];
|