RAC系列2之 基础篇2
ReactiveCocoa开发中常见方法
rac_signalForSelector
:- 原理:把调用某个对象的方法转换成信号,只要调用这个方法,就会发送信号。只要提前订阅这个信号就可以监听这个对象的调用了.
- 作用: 监听对象的某个方法有没有调用
- KVO(
rac_valuesForKeyPath
和rac_valuesAndChangesForKeyPath
) :- 原理: 把监听对象的属性改变转换成信号,只要只改变就发送信号
rac_signalForControlEvents
:- 作用:用于监听某个事件
- 原理: 把按钮的的点击事件转换为信号,点击按钮,就回发送信号
rac_addObserverForName
:- 作用:用于监听某个通知。
- OC用完观察者之后需要移除观察者,但是RAC不需要管理观察者,内部已经管理好了
rac_textSignal
:- 作用: 监听文本框文字改变
rac_liftSelector:withSignalsFromArray:
:- 作用: 处理当一个界面有多次请求时,需要都获取到数据时,才能展示界面
- 当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法。
- 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。
-
代码举例
//1. rac_signalForSelector //自定义RedView,实现touchBegan方法 //viewController控制器 -(void)viewDidLoad{ RedView *redV = [[RedView alloc] init]; redV.backgroundColor = [UIColor redColor]; redV.frame = CGRectMake(50, 50, 100, 100); [self.view addSubview:redV]; [[redV rac_signalForSelector:@selector(touchesBegan:withEvent:)] subscribeNext:^(id _Nullable x) { NSLog(@"点击View"); }]; } //2. KVO -(void)viewDidLoad{ //KVO RedView *redV = [[RedView alloc] init]; redV.backgroundColor = [UIColor redColor]; redV.frame = CGRectMake(50, 50, 100, 100); [self.view addSubview:redV]; _redV = redV; //把监听redview的frame属性改变转换成信号,只要只改变就发送信号 //方法1: //程序一启动,加载RedView就会改变frame,因此开始就会调用一次 [[redV rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id _Nullable x) { NSLog(@"--监听属性值---"); }]; //方法2: //程序启动加载redView时不会调用 [[redV rac_valuesAndChangesForKeyPath:@"frame" options:NSKeyValueObservingOptionNew observer:self] subscribeNext:^(RACTwoTuple<id,NSDictionary *> * _Nullable x) { NSLog(@"--监听属性变化---"); }]; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ self.redV.frame = CGRectMake(100, 100, 200, 200); } //3. 监听事件 UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 50, 50)]; btn.backgroundColor = [UIColor redColor]; [self.view addSubview:btn]; //监听事件 //把按钮的的点击事件转换为信号,点击按钮,就回发送信号 [[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) { NSLog(@"点击了按钮"); }]; //4. 监听通知 -(void)viewDidLoad{ UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 200, 30)]; textField.backgroundColor = [UIColor redColor]; [self.view addSubview:textField]; //监听键盘弹出的通知 //RAC监听 [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) { NSLog(@"键盘将要弹出了"); }]; //OC监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sss:) name:UIKeyboardWillShowNotification object:nil]; } -(void)sss:(id)d{ NSLog(@"键盘将要sss弹出了"); } //5.监听文本框的文字改变 -(void)viewDidLoad{ UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 200, 30)]; textField.backgroundColor = [UIColor redColor]; [self.view addSubview:textField]; //监听TextField内容改变 [textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) { NSLog(@"=====%@",x); }]; } //6. 同时获取到数据,刷新UI -(void)viewDidLoad{ //处理当一个界面有多次请求时,需要都获取到数据时,才能展示界面 //网络请求1 RACSignal *signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"网络请求1") ; [subscriber sendNext:@"网络请求1获取到的数据"]; [subscriber sendCompleted]; return nil; }]; //网络请求2 RACSignal *signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { NSLog(@"网络请求2") ; [subscriber sendNext:@"网络请求2获取到的数据"]; [subscriber sendCompleted]; return nil; }]; //保证两个请求都完成的情况下才能刷新UI /* 数组用于存放信号 selector:当数组中的信号都发送数据的时候,才会调用 selector参数个数: 与数组中的信号个数一样 selector参数类型: 与数组中对应的信号发出的数据一一对应 */ [self rac_liftSelector:@selector(obtainData1: andData2:) withSignalsFromArray:@[signal1,signal2]]; } //同时获取到数据,刷新UI -(void)obtainData1:(NSString *)data1 andData2: (NSString *)data2{ NSLog(@"数据1===%@===数据2===%@",data1,data2); }
ReactiveCocoa常见宏
RAC(TARGET, ...)
- 作用: 用于给某个对象的某个属性绑定。
-
代码举例:
-(void)viewDidLoad{ UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 200, 30)]; textField.backgroundColor = [UIColor redColor]; [self.view addSubview:textField]; UILabel *label = [[UILabel alloc] init]; label.frame = CGRectMake(100, 300, 200, 30); [self.view addSubview: label]; //方法1: [textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) { label.text = x; }]; //方法2: RAC(label,text) = textField.rac_textSignal; }
RACObserve(TARGET, KEYPATH)
:- 作用: 监听某个对象的某个属性,返回的是信号。
-
代码举例:
[RACObserve(self.view, center) subscribeNext:^(id _Nullable x) { NSLog(@"属性改变%@",x); }];
@weakify(Obj)
和@strongify(Obj)
:- 一般两个都是配套使用
- 解决block的循环引用问题
-
代码举例:
#import "TwoViewController.h" #import <ReactiveObjC/ReactiveObjC.h> @interface TwoViewController () @property (nonatomic,strong) RACSignal *signal ; @end @implementation TwoViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; @weakify(self); RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) { @strongify(self); NSLog(@"%@",self); return nil; }]; self.signal = signal; } -(void)dealloc{ NSLog(@"%s",__func__); } @end
- RACTuplePack
- 作用:把数据包装成RACTuple(元组类)
-
代码:
// 把参数中的数据包装成元组 RACTuple *tuple = RACTuplePack(@10,@20);
RACTupleUnpack
- 作用: 把RACTuple(元组类)解包成对应的数据。
-
代码:
// 把参数中的数据包装成元组 RACTuple *tuple = RACTuplePack(@"xmg",@20); // 解包元组,会把元组的值,按顺序给参数里面的变量赋值 // name = @"xmg" age = @20 RACTupleUnpack(NSString *name,NSNumber *age) = tuple;