一,取代代理:
场景:比如说在导航栏下有page1controller和page2controller,在page2controller 上的一个btn被点击的时候向上传递告诉page1controller
那么需要如下代码:
1,在page2controller的.h中定义如下RACSubject,暴漏给page1控制器:
@property (nonatomic, strong) RACSubject *subject;
2,page2controller的.m文件中懒加载RACSubject,并在点击按钮的时候发送信号数据,如下:
@implementation IMPage2ViewController
#pragma mark- lazy
- (RACSubject *)subject{
if (_subject == nil) {
_subject = [RACSubject subject];
}
return _subject;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)btnDidClicked:(id)sender {
[self.subject sendNext:@"controller2向1传递数据"];
}
@end
3,在page1控制器中,通过prepareForSegue方法来订阅来自page2控制器的信号,如下:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[super prepareForSegue:segue sender:sender];
IMPage2ViewController *page2Controller = segue.destinationViewController;
[page2Controller.subject subscribeNext:^(id x) {
NSLog(@"接收到数据,数据内容是:%@",x);
}];
}
注意:
另外如果不需要传递数据的情况下,只传递点击事件的时候这种方式还可以简化成一句代码:
上面1,2步骤中rac的所有代码均可以省略,只需要在page1控制器中监听page2控制器按钮点击方法然后转化成信号,直接添加订阅即可,如下:
1,在page2controller的.h中不用定义如下RACSubject,但是需要把点击事件方法暴漏给page1控制器:
//这里可以直接省略
//@property (nonatomic, strong) RACSubject *subject;
- (IBAction)btnDidClicked:(id)sender ;
2,page2controller的.m文件中也就不用懒加载RACSubject
@implementation IMPage2ViewController
#pragma mark- lazy
/*
- (RACSubject *)subject{
if (_subject == nil) {
_subject = [RACSubject subject];
}
return _subject;
}
*/
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)btnDidClicked:(id)sender {
//这里只需要把方法实现一下即可,无需任何rac代码,但是需要把该方法在.h文件中暴漏出去
//[self.subject sendNext:@"controller2向1传递数据"];
}
@end
3,在page1控制器中,通过prepareForSegue方法来订阅来自page2控制器的信号,如下:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[super prepareForSegue:segue sender:sender];
IMPage2ViewController *page2Controller = segue.destinationViewController;
//方式二,不需要传递数据,只需要传递点击事件
[[page2Controller rac_signalForSelector:@selector(btnDidClicked:)] subscribeNext:^(id x) {
NSLog(@"利用方式二方式进行监听事件点击,方式二方便但是不能进行数据传递");
}];
}
二,取代KVO
系统KVO是通过监听属性改变,然后调用代理方法进行告知,如果说一个控制器需要监听多个属性改变,代理方法中就需要判断属性然后才能做出相应的操作,而RAC代替kvo直接是用block进行告知,可以直接在block中对属性进行相应的操作,实现代码的高聚合,如下:
有两种取代方式:
1,第一种是直接监听,只能得到改变后的值,如下:
[[self.view rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id x) {
NSLog(@"监听到改变---%@",x);
}];
//这个改变的时候输出结果是:NSRect: {{0, 0}, {500, 440}}
2,第二种是监听改变,如果option时new,得到一个元组,仍然是得不到旧值,如下
[[self.view rac_valuesAndChangesForKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionOld observer:self] subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
/*
//输出结果是元组:
//如果是NSKeyValueObservingOptionNew,只有新值,如下
(
"UIExtendedSRGBColorSpace 0 0 1 1",
{
kind = 1;
new = "UIExtendedSRGBColorSpace 0 0 1 1";
}
)
*/
//如果是NSKeyValueObservingOptionOld,结果中既有旧值,又有新值,如下
/*
(
"UIExtendedSRGBColorSpace 0 0 1 1",
{
kind = 1;
old = "UIExtendedSRGBColorSpace 1 1 1 1";
}
)
*/
```
3,取代kvo高级用法:宏RACObserve
//RACObserve(<#TARGET#>, <#KEYPATH#>) 相当于 [TARGET rac_valuesForKeyPath:<#(NSString *)#> observer:<#(NSObject *__weak)#>]
[RACObserve(self.view, backgroundColor) subscribeNext:^(id x) {
NSLog(@"%@", x);
}];
###三,取代addTarget监听
* 取代监听事件,比如自身的一个btn,通过block取代addTarget,不需要把点击事件相应操作放在另外方法中,实现高聚合,如下:
[[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
NSLog(@"按钮被点击");
}];
###四,取代通知方法
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
###五,监听文本框文字改变
[[_textField rac_textSignal] subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
//监听文字改变的高级宏用法(可以直接把监听到文字改变赋值给另外的控件)
RAC(self.label, text) = _textField.rac_textSignal;
}