zoukankan      html  css  js  c++  java
  • ReactiveCocoa 初识

    1.ReactiveCocoa(简称RAC),是有Github开源的一个应用于iOS和OS开发的心框架,Cocoa是苹果框架的简称,因此很多苹果框架都喜欢以Cocoa结尾,他开辟的Object-C编程的新纪元,他的厉害之处在与他的编程思想.

    2.编程思想:

    函数响应式编程:(Functional Reactive Programming)简称(FRP);

    我们已知的编程思想:

    2.1面向过程:处理事情以过程为核心,一步一步的实现.

    2.2面向对象:万物皆对象

    2.3链式编程思想:是将多个操作(多行代码)通过点(.)连接在一起成为一句代码,使代码的可读性好.

    链式编程的特点:方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)

    响应式编程思想:不需要考虑调用顺序,只需要知道考虑结果,是代码高内聚,低耦合,方便管理,类似蝴蝶效应,产生一个事件,会影响很多东西,这些事件就像流一样传播出去,然后影响结果,借用面向对象的一句话,万物皆是流.

    3.Reactivecocoa的作用:

    3.1在iOS开发过程中,当某些事件响应的时候,需要处理某些业务逻辑,这些事件都用不同的方式来处理.

    3.2比如按钮点击使用action, ScrollView滚动使用delegate,属性值改变使用KVO等系统提供的方式.

    3.3其实某些事件,都可以通过RAC处理

    3.4ReactiveCocoa为事件提供了很多处理方法,而且利用RAC处理事件很方便,可以把要处理的事情,和监听的事情的代码放在一起,这样方便我们管理,就不需要跳到对应的方法里面去了,非常符合我们开发中的高内聚,低耦合的思想.

    4.使用CocoaPods导入Reactivecocoa框架:

    通常都会使用CocoaPods(用于管理第三方框架的插件)帮助我们导入。

    PS:CocoaPods教程

    注意

    • podfile如果只描述pod 'ReactiveCocoa', '~> 4.0.2-alpha-1',会导入不成功。


      Snip20150926_1.png
    • 报错提示信息


    Snip20150926_2.png
    • 需要在podfile加上use_frameworks,重新pod install 才能导入成功。

     
    5.ReactiveCocoa中常见的类:
    在RAC中最核心的类就是RACSignal,搞定这个类就能用ReactiveCocoa开发了.
    RACSignal:信号类,一般表示将来有数据传递,只要数据改变,信号内部就会收到数据,就会马上发出数据.
    注意:
    信号类:(RACSignal),只是表示数据改变时,信号内部会发出数据,他本身不具备发送信号的能力,而是交给内部一个订阅者去发出.
     

    RACSubscriber:表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方法才能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。

    RACDisposable:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。

    • 使用场景:不想监听某个信号时,可以通过它主动取消订阅信号。

     RACSubject:RACSubject:信号提供者,自己可以充当信号,又能发送信号。

    • 使用场景:通常用来代替代理,有了它,就不必要定义代理了。

    RACReplaySubject:重复提供信号类,RACSubject的子类。

    • RACReplaySubjectRACSubject区别:
      • RACReplaySubject可以先发送信号,在订阅信号,RACSubject就不可以。
    • 使用场景一:如果一个信号每被订阅一次,就需要把之前的值重复发送一遍,使用重复提供信号类。
    • 使用场景二:可以设置capacity数量来限制缓存的value的数量,即只缓充最新的几个值。

     

    6.ReactiveCocoa开发中常见用法。

    6.1 代替代理: 

    • rac_signalForSelector:用于替代代理。

    6.2 代替KVO : 

    • rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变。

    6.3 监听事件: 

    • rac_signalForControlEvents:用于监听某个事件。

    6.4 代替通知: 

    • rac_addObserverForName:用于监听某个通知。

    6.5 监听文本框文字改变: 

    • rac_textSignal:只要文本框发出改变就会发出这个信号。

    6.6 处理当界面有多次请求时,需要都获取到数据时,才能展示界面

    • rac_liftSelector:withSignalsFromArray:Signals:当传入的Signals(信号数组),每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法。
    • 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。

    下面的代码是我自己练习的:

        //RAC为系统的很多类拓展了功能,例如textfield为我们提供一个叫做rac_textSingnal的属性,(RAC的拓展都已rac开头),singnal是信号的意思,我们订阅一个信号后,可以接收信号发送的消息;

        //1.发送消息

        //2.订阅消息

        //参数:接收到消息后的一些处理操作;

        //下面操作会造成循环引用

        [self.myTextField.rac_textSignal subscribeNext:^(id x) {

    //

            self.myLable.text = x;

        }];

        //解决方案 (弱引用与强引用)

        @weakify(self);

        [self.myTextField.rac_textSignal subscribeNext:^(id x) {

    //

            @strongify(self);

            self.myLable.text = x;

        }];

        //也可以这么写

        //RAC为我们提供很方便的一个宏,将信号发送的值直接复制给某个属性

        RAC(self.myLable, text) = self.myTextField.rac_textSignal;

        

        //给lable添加监听者

        //KVO 键值监听(Key -- Value -- Observer)

        //添加观察者为self

        //观察那个属性

        //关注的是旧值还是新值

        [self.myTextField addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];

        

        //RAC又给我们提供了一个宏

        [RACObserve(self, count) subscribeNext:^(id x) {

           

            NSLog(@"observer = %@", x);

            

        }];

        

        //自己创建一个信号

        RACSignal *singnal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

            

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                

                [subscriber sendNext:@"aaa"];

                [subscriber sendCompleted];

                

                

            });

            

            return [RACDisposable disposableWithBlock:^{

                

                NSLog(@"操作销毁");

            }];

        }];

        //订阅信号

        [singnal subscribeNext:^(id x) {

           

            NSLog(@"自定义信号:%@", x);

            

        }];

        

        

        

    }

    //监听

    //-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{

    //    

    //    

    //    NSLog(@"keyPath = %@, change = %@", keyPath, change);

    //    

    //}

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

        

        self.count ++;

    }

  • 相关阅读:
    .csproj文件
    堆栈
    数据库操作(一)
    Math数学函数
    SSM框架下各个层的解释说明
    MyBatis DAO层传递参数到mapping.xml
    Spring MVC3在controller和视图之间传递参数的方法
    注册/登陆界面验证码的作用及代码实现
    input中name和id的区别
    <mvc:default-servlet-handler/>的作用
  • 原文地址:https://www.cnblogs.com/LzwBlog/p/5398713.html
Copyright © 2011-2022 走看看