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 ++;

}

原文地址:https://www.cnblogs.com/LzwBlog/p/5398713.html