RAC的应用场景(取代代理,通知,KVO等)

一,取代代理:

场景:比如说在导航栏下有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;
    
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容