#iOS RAC 的基本用法 和 高级用法
##1监听方法
####现在有以下场景
控制器VC里面有一个视图ViewA ,ViewA 里面有一个button 的私有属性。现在想button 的点击来到控制器做一些动作。这个时候老司机都懂得,使用Block 或者使用代理可以很好的解决这个办法,但是这么写的话是在稍显麻烦,有没有更简单的办法可以实现呢?其实用RAC就可以很好的解决这个问题。先看代码ViewA
#import "XJRedView.h"
@interface XJRedView ()
@property (nonatomic,strong) UIButton *button; //点击按钮
@end
@implementation XJRedView
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor redColor];
self.button = [UIButton buttonWithType:UIButtonTypeContactAdd];
[self.button sizeToFit];
self.button.center = self.center;
[self addSubview:self.button];
[self.button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
return self;;
}
-(void)buttonClick:(UIButton *)button{
NSLog(@"====%@=====%@",NSStringFromClass(self.class),NSStringFromSelector(_cmd));
}
然后就是VC上的内容 redView == ViewA
只需要通过
[[self.redView rac_signalForSelector:@selector(buttonClick:)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"button被点击了%@",NSStringFromSelector(_cmd));
}];
然后我们看下这个输出结果。
2020-11-05 15:15:27.430445+0800 test[20637:218919] ====XJRedView=====rac_alias_buttonClick:
2020-11-05 15:15:27.430775+0800 test[20637:218919] button被点击了viewDidLoad
是不是很方便,具体原理 后面文章补充。现在只写用法。
###KVO
通常我们要使用KVO需要addObserver并且还要在observeValueForKeyPath...这个方法中去监听,
如果一个界面监听多个还需要判断,还必须记得释放掉。
但是这些东西在RAC中就做了一层包装,现在我们如果想监听对象的某个属性,就可以写如下代码就可以完成,
并且针对某个属性都会产生不同的信号,我们只需要监听所产生的信号在进行处理就可以了
那么RAC 的监听是怎么进行的呢?代码如下,
-(void)test2KVO{
[RACObserve(self, times)subscribeNext:^(id _Nullable x) {
NSLog(@"==监听到了%@--方法名称是%@",x,NSStringFromSelector(_cmd));
}];
}
-(void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event{ self.times ++;
}
看输出
`2020-11-05 15:44:24.792855+0800 test[20902:242261] ==监听到了0--方法名称是test2KVO
2020-11-05 15:44:37.126733+0800 test[20902:242261] ==监听到了1--方法名称是test2KVO
2020-11-05 15:44:37.307346+0800 test[20902:242261] ==监听到了2--方法名称是test2KVO
2020-11-05 15:44:37.503726+0800 test[20902:242261] ==监听到了3--方法名称是test2KVO
可以看出 当 times 初始值的时候也触动了 KVO。监听的方式有很多种,我常用的就这一种。如果观众老爷想去看看别的监听 请自行百度。
###监听事件 ----不用手动销毁
假如我此VC 中有一个button, 可以高内聚的写法,如下 (还不如我runtime 给button增加一个点击的Block 属性 来的简单粗暴);
-(void)testButton{
[[self.button rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(__kindof UIControl * _Nullable x) {
NSLog(@"我被点击了%@",NSStringFromSelector(_cmd));
}];
}
###通知 --- 不用手动销毁
[[[NSNotificationCenter defaultCenter]rac_addObserverForName:@"接受通知的字段" object:nil] subscribeNext:^(NSNotification * _Nullable x) {
NSLog(@"接受到通知了");
}];
###监听 ---个人认为最好用的就是这个
[_textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
NSLog(@"%@",x);
}];
###代替代理
还按照最上面的场景,但是我这次需要以代理的方式让button的点击事件回应在VC中,应该怎么做呢。
#####第一步,添加信号属性 并初始化信号。
.h
@interface XJRedView : UIView
@property (nonatomic,strong) RACSubject *buttonClickSingal; //button 被点击的信号。
@end
.m
///初始化这个信号。
-(RACSubject *)buttonClickSingal{
if (!_buttonClickSingal) {
_buttonClickSingal = [RACSubject subject];
}
return _buttonClickSingal;
}
######第二步,发送信号。
///发送这个信号。
-(void)buttonClick:(UIButton *)button{
[_buttonClickSingal sendNext:button];
}
#####第三步,接收这个信号(订阅,在合适的地方)
///订阅这个信号
[_redView.buttonClickSingal subscribeNext:^(id _Nullable x) {
NSLog(@"%@",x);
}];