美文网首页
ReactiveCocoa(RAC)框架

ReactiveCocoa(RAC)框架

作者: King_Liu | 来源:发表于2016-10-20 15:55 被阅读50次

    简介

    什么是RAC?ReactiveCocoa(简称RAC),是由Github开源的一个应用于iOS和OS开发的新框架,Cocoa是苹果整套框架的简称,因此很多苹果框架喜欢以Cocoa结尾。借用RayWenderlich上面的话:

    As an iOS developer, nearly every line of code you write is in reaction to some event; a button tap, a received network message, a property change (via Key Value Observing) or a change in user’s location via CoreLocation are all good examples. However, these events are all encoded in different ways; as actions, delegates, KVO, callbacks and others. ReactiveCocoa defines a standard interface for events, so they can be more easily chained, filtered and composed using a basic set of tools.

    翻译过来就是:

    作为一个iOS开发者,你写的每一行代码几乎都是在响应某个事件,例如按钮的点击,收到网络消息,属性的变化(通过KVO)或者用户位置的变化(通过CoreLocation)
    。但是这些事件都用不同的方式来处理,比如action、delegate、KVO、callback等
    。ReactiveCocoa为事件定义了一个标准接口,从而可以使用一些基本工具来更容易的连接、过滤和组合。

    RAC是由Matt Thompson大神开发的,很多开发者对其的评价是开启一个新的Objective-C纪元。

    安装

    ReactiveCocoa用pod安装即可。
    本文的Demo可在文章最后下载,在阅读本文的时候,强烈推荐边看Demo边看博文。
    项目中加入了ReactiveCocoa和DeveloperLx的打印插件LxDBAnything同时加入了键盘相应的第三方IQKeyboardManager,以及Masonry,使用方法可以看这篇文章:iOS – Masonry自动布局(Autolayout)

    代码

    第一部分 简单使用

    文本框事件

    原来我们在使用textFiled的时候我们需要写到

    [textField addTarget:self action:@selector(textChanged:) forControlEvents:UIControlEventEditingChanged];
    

    然后实现textChanged:方法,在RAC中,对于文本框的监听,是非常简单的一件事情,看如下代码:

    UITextField * textField = ({
           UITextField * textField = [[UITextField alloc]init];
           textField.backgroundColor = [UIColor cyanColor];
           
           textField;
       });
      [self.view addSubview:textField];
       
       @weakify(self); //  __weak __typeof__(self) self_weak_ = self;
       
       [textField mas_makeConstraints:^(MASConstraintMaker *make) {
           
           @strongify(self);    // __strong __typeof__(self) self = self_weak_;
           make.size.mas_equalTo(CGSizeMake(180, 40));
           make.center.equalTo(self.view);
       }];
       
       [[textField rac_signalForControlEvents:UIControlEventEditingChanged]
        subscribeNext:^(id x) {
            
            LxDBAnyVar(x);
        }];
       [textField.rac_textSignal subscribeNext:^(NSString *x) {
           
           LxDBAnyVar(x);
       }];
    

    打印结果:

    📍__31-[ViewController textFiledTest]_block_invoke_2 + 215🎈 x = 12
    📍__31-[ViewController textFiledTest]_block_invoke241 + 211🎈 x = 0x7fe810c51a90; frame = (97.5 313.5; 180 40); text = '123'; clipsToBounds = YES; opaque = NO; gestureRecognizers = 0x7fe810f58fb0>; layer = 0x7fe810c51600>>
    📍__31-[ViewController textFiledTest]_block_invoke_2 + 215🎈 x = 123
    📍__31-[ViewController textFiledTest]_block_invoke241 + 211🎈 x = 0x7fe810c51a90; frame = (97.5 313.5; 180 40); text = '1231'; clipsToBounds = YES; opaque = NO; gestureRecognizers = 0x7fe810f58fb0>; layer = 0x7fe810c51600>>
    📍__31-[ViewController textFiledTest]_block_invoke_2 + 215🎈 x = 1231
    📍__31-[ViewController textFiledTest]_block_invoke241 + 211🎈 x = 0x7fe810c51a90; frame = (97.5 313.5; 180 40); text = '12312'; clipsToBounds = YES; opaque = NO; gestureRecognizers = 0x7fe810f58fb0>; layer = 0x7fe810c51600>>
    📍__31-[ViewController textFiledTest]_block_invoke_2 + 215🎈 x = 12312
    📍__31-[ViewController textFiledTest]_block_invoke241 + 211🎈 x = 0x7fe810c51a90; frame = (97.5 313.5; 180 40); text = '123123'; clipsToBounds = YES; opaque = NO; gestureRecognizers = 0x7fe810f58fb0>; layer = 0x7fe810c51600>>
    📍__31-[ViewController textFiledTest]_block_invoke_2 + 215🎈 x = 123123
    

    我们很容易的监听到textFiled中发生的变化,其中x的类型默认为id类型,我们已知它的类型的时候我们可以将其改变,就像上面代码,将id改成NSString类型。

    手势

    self.view.userInteractionEnabled = YES;
        UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc]init];
        [[tap rac_gestureSignal] subscribeNext:^(UITapGestureRecognizer * tap) {
            
            LxDBAnyVar(tap);
        }];
        [self.view addGestureRecognizer:tap];
    

    为了方便,我们直接添加到self.view上,点击屏幕,得到打印结果:

    📍__29-[ViewController gestureTest]_block_invoke + 184🎈 tap = 0x7fa2e3e1f9f0; state = Ended; view = 0x7fa2e3e20b70>; target= action=sendNext:, target=0x7fa2e3c064f0>)>>
    

    通知

    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] subscribeNext:^(NSNotification * notification) {
           
           LxDBAnyVar(notification);
       }];
    

    我们建立了一个通知,叫做进入后台,当程序进入后台的时候通知相应,当我们用RAC写通知的时候,我们有一个好处,就是不用removeObserve通知,因为RAC通知的监听者是RAC自己,它会帮你管理释放方法。可以看方法实现如下:

    - (RACSignal *)rac_addObserverForName:(NSString *)notificationName object:(id)object {
        @unsafeify(object);
        return [[RACSignal createSignal:^(idRACSubscriber> subscriber) {
            @strongify(object);
            id observer = [self addObserverForName:notificationName object:object queue:nil usingBlock:^(NSNotification *note) {
                [subscriber sendNext:note];
            }];
    
            return [RACDisposable disposableWithBlock:^{
                [self removeObserver:observer];
            }];
        }] setNameWithFormat:@"-rac_addObserverForName: %@ object: ", notificationName, [object class], object];
    }
    

    定时器

    //1. 延迟某个时间后再做某件事
    [[RACScheduler mainThreadScheduler]afterDelay:2 schedule:^{
        
        LxPrintAnything(rac);
    }];
    
    //2. 每间隔多长时间做一件事
    [[RACSignal interval:1 onScheduler:[RACScheduler mainThreadScheduler]]subscribeNext:^(NSDate * date) {
        
        LxDBAnyVar(date);
    }];
    

    这是定时器最常用的两种写法,第一种方法,延迟时间去做某件事情,更改afterDelay的属性。
    第二种方法,每间隔多长时间做一件事情,更改interval属性。

    代理

    UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"RAC" message:@"ReactiveCocoa" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Ensure", nil];
       
       [[self rac_signalForSelector:@selector(alertView:clickedButtonAtIndex:) fromProtocol:@protocol(UIAlertViewDelegate)] subscribeNext:^(RACTuple * tuple) {
           
           LxDBAnyVar(tuple);
           
           LxDBAnyVar(tuple.first);
           LxDBAnyVar(tuple.second);
           LxDBAnyVar(tuple.third);
       }];
       [alertView show];
       
       
       //   更简单的方式:
       [[alertView rac_buttonClickedSignal]subscribeNext:^(id x) {
           
           LxDBAnyVar(x);
       }];
    

    用RAC去写代理的时候,会有局限,只能取代没有返回值的代理方法,什么是没有返回值的代理呢?比如说tableView的代理方法:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    

    相关文章

      网友评论

          本文标题:ReactiveCocoa(RAC)框架

          本文链接:https://www.haomeiwen.com/subject/opwfuttx.html