前言

 应用通常会消费、制造和更新数据。响应式编程是一种编程范式,能够表示数据流,而无需担心副作用或对其他并发执行的任务造成影响。

 响应式编程背后的核心思想是随时间流逝体现数据的值。使用动态值的数据流会导致这些值随着时间而变化。

 函数响应式编程(functional reactive programmingFRP)允许响应式编程使用内建的块方法进行函数式编程,如mapreducefiltermerge,等等。

 ReactiveCocoa 的灵感来自 FRP。因为多组件的应用以高内聚的方式工作,所以组件状态的使用和更新就有了很强的关联。正因为这一点,创建一个低耦合、高内 聚的响应式系统才显得尤为重要。

现在有下面4个概念:

    面向对象编程 Object Oriented Programming
    响应式编程 Reactive Programming
    函数式编程 Functional Programming
    函数响应式编程 Functional Reactive Programming


Reactive Cocoa 是一个重量级框架,非常的牛,为什么说Reactive Cocoa非常的牛?
我们所熟知的iOS 开发中的事件包括:

  • Target
  • Delegate
  • KVO
  • 通知
  • 时钟
  • 网络异步回调

ReactiveCocoa ,就是用信号接管了iOS 中的所有事件;也就意味着,用一种统一的方式来处理iOS中的所有事件,解决了各种分散的事件处理方式,显然这么一个庞大的框架学习起来也会比较难!

先看一个图:
函数响应式编程(FRP)与 ReactiveCocoa


从这张图中,可以看出利用信号,ReactiveCocoa接管iOS 的所有事件,抛给开发者对事件作出三个相应反应;

可以用一张图来简要说明

函数响应式编程(FRP)与 ReactiveCocoa


   

RAC 的特点

  • 通过 block 函数式 + 链式 的编程,可以让所有相关的代码继承在一起!

  • 使用时需要注意循环引用,@weakify(self) / @strongify(self) 组合解除循环引用;
下面用iOS开发中常见的五种事件来说明ReactiveCocoa的常见用法!

   

下载框架:

  • 新建iOS工程
  • 进入终端,建立 Podfile,并且输入以下内容
        函数响应式编程(FRP)与 ReactiveCocoa


 在终端输入以下命令安装框架

  $ pod install       

 

常见用法

KVO 监听

        程序实现: 监控Person name的属性变化;在touchesBegan中改变name的值,并将变化体现在UILabel上,实现KVO的监控功能;

  • 注意,RAC 的信号一旦注册不会主动释放
  • 只要在 block 中包含有 self. 一定会出现强引用* 需要使用 @weakify(self) / @strongify(self) 组合使用解除强引用
函数响应式编程(FRP)与 ReactiveCocoa函数响应式编程(FRP)与 ReactiveCocoa函数响应式编程(FRP)与 ReactiveCocoa函数响应式编程(FRP)与 ReactiveCocoa函数响应式编程(FRP)与 ReactiveCocoa函数响应式编程(FRP)与 ReactiveCocoa

         



   文本框输入事件监听

函数响应式编程(FRP)与 ReactiveCocoa

函数响应式编程(FRP)与 ReactiveCocoa


函数响应式编程(FRP)与 ReactiveCocoa



   

文本框组合信号

函数响应式编程(FRP)与 ReactiveCocoa


函数响应式编程(FRP)与 ReactiveCocoa


按钮监听

函数响应式编程(FRP)与 ReactiveCocoa

按钮点击后看日志输出

函数响应式编程(FRP)与 ReactiveCocoa


代理方法

函数响应式编程(FRP)与 ReactiveCocoa


函数响应式编程(FRP)与 ReactiveCocoa



通知

viewDidLoad 中添加

函数响应式编程(FRP)与 ReactiveCocoa


函数响应式编程(FRP)与 ReactiveCocoa

 

高级用法

 1. flattenMapmap

    函数响应式编程(FRP)与 ReactiveCocoa


    merge:把多个信号合并成一个信号,只需订阅这一个信号就相当于订阅了多个信号,任何一个信号有新值的时候都会触发调用。

       函数响应式编程(FRP)与 ReactiveCocoa


concat:将多个信号有顺序的连接起来,按照顺序接收信号,但是一定要之前的信号完成了才能发送下一个信号。

函数响应式编程(FRP)与 ReactiveCocoa

     then:用于连接两个信号,内部也是使用concat,当前一个信号完成之后才会连接then返回的信号,但是会忽略前一个信号,只会触发下个信号。

           函数响应式编程(FRP)与 ReactiveCocoa


zip:将对各信号压缩成一个信号,只有当几个信号同时sendNext的时候才会触发压缩流的next事件,其中每一个信号send的内容都是一一对应的。


函数响应式编程(FRP)与 ReactiveCocoa

combineLatest:将多个信号组合起来,当其中每一个信号都sendNext之后,才会触发组合的信号,其中每一个信号再次sendNext都会覆盖之前的信号内容,返回的是一个RACTuple(元组,类似于NSArray)。

函数响应式编程(FRP)与 ReactiveCocoa


rac_liftSelector: withSignalsFromArray::当信号组中每一个信号都至少一次sendNext之后,将触发Selector方法,类似于combineLatest


函数响应式编程(FRP)与 ReactiveCocoa


reduceEach:一般用于元组,把元组的值聚合成一个值。

函数响应式编程(FRP)与 ReactiveCocoa


filter:过滤信号,添加筛选条件,只有符合的才会触发调用。

函数响应式编程(FRP)与 ReactiveCocoa


distinctUntilChanged:当前值跟上一次的值不同的时候,就会触发调用,否则被忽略。

函数响应式编程(FRP)与 ReactiveCocoa

函数响应式编程(FRP)与 ReactiveCocoa


take:从第一个信号开始设置信号发送的有效的个数。

函数响应式编程(FRP)与 ReactiveCocoa


takeLast:从最后一个开始设置信号发送的有效个数,必须sendCompleted,不然不知道总共多少个信号。

函数响应式编程(FRP)与 ReactiveCocoa


takeUntil[signal1 takeUntil:signal2],当signal2已经sendNext或者sendCompleted,signal1就会失效。

函数响应式编程(FRP)与 ReactiveCocoa


skip:跳跃,从第一个发出的信号开始跳。

函数响应式编程(FRP)与 ReactiveCocoa

doNext:在执行sendNext之前会执行这个。

函数响应式编程(FRP)与 ReactiveCocoa

timeout:在超过设定时间范围之后让信号报错,且不能发送内容。

函数响应式编程(FRP)与 ReactiveCocoa

interval:定时,每隔一定时间发出时间信号。

函数响应式编程(FRP)与 ReactiveCocoa


delay:延时发送信号

函数响应式编程(FRP)与 ReactiveCocoa

retry:重试,只要失败,就会重新执行创建信号中的block,直到成功。

函数响应式编程(FRP)与 ReactiveCocoa


throttle:节流,当某个信号发送比较频繁的时候,可以限制在一定之间内不接受信号,等过了这个时间再取最后发送的信号内容发出,类似于bufferWithTime:onScheduler:

函数响应式编程(FRP)与 ReactiveCocoa

deliverOn:内容传递切换到指定线程中,副作用在原来线程中,把在创建信号时block中的代码称之为副作用。

subscribeOn:内容传递和副作用都会切换到指定线程中。


        RACSubject

信号提供者,本身可以充当信号,又能发送信号,继承自RACSignal,但是底层实现跟RACSignal有些不一样,当订阅信号的时候会创建订阅者并保存订阅响应Block,而发送信号的时候会遍历订阅者,然后分别调用nextBlock。它提供的API很少,但是经常使用,因为它继承自RACSignal。这里顺便来看一下方法flattenswitchToLatest,这两个都只能用来处理信号中的信号。

flatten:压平信号中的信号,信号中的信号我们称之为子信号,flatten可以拿到所有子信号发送的值。

函数响应式编程(FRP)与 ReactiveCocoa

switchToLatest:与flatten相同,压平信号中的信号,不同的是,在存在多个子信号时候只会拿到最新的子信号,然后输出最新的子信号的

函数响应式编程(FRP)与 ReactiveCocoa



RACReplaySubject

重复提供信号类,继承自RACSubject,它可以先发送信号,再订阅信号,原理就是将发送的信号内容保存了起来,当订阅信号的时候再将之前保存的信号,由订阅者一个一个的发送出来,而保存信号的容量由capacity来控制。

 函数响应式编程(FRP)与 ReactiveCocoa


RACMulticastConnection

这是一个组播连接类,是对信号的一个封装处理,当一个信号被多次订阅时,则会多次执行didSubscribe这个Block,造成副作用,而这个类就能避免多次执行didSubscribe,是一对多的单向数据流,一般用来处理信号被多次订阅的情况。

函数响应式编程(FRP)与 ReactiveCocoa

方法解析及实现原理
  • publishmulticast:这是对RACMulticastConnection初始化方法的一个封装,publish其实就是调用了multicast,并把创建好的RACSubject对象传给它,而multicast也就是调用了RACMulticastConnection的初始化方法,将原始信号传给source,把RACSubject对象传给subject
  • 当我们订阅connect.signal,其实就是订阅subject,然后将subject的订阅者保存起来,而调用[connect connect]的时候,会订阅原始信号(source),而source的订阅者就是subject,这时候subject就会执行[subject sendNext],之后就会遍历subject所有的订阅者,逐一发送信号,触发外部subscribeNext回调。

RACCommand

这是一个命令类,可以把事件如何处理,事件中的数据如何传递,包装到这个类中,他可以很方便的监控事件的执行过程,一般来说是在UI上的某些动作来触发这些事件,比如点击一个按钮,RACCommand的实例能够决定是否可以被执行,一般用于网络请求,监控请求过程。

函数响应式编程(FRP)与 ReactiveCocoa

RACChannel

这是一个通道类,可以理解为一个双向的连接,连接的两端都配有RACChannelTerminal(通道终端,继承自RACSignal,且又实现了RACSubscriber协议,所以它可以充当信号,又能发送信号),分别是leadingTerminalfollowingTerminal,只要其中任何一端输出信号,另一端都会有相同的信号输出。我们平时很少直接使用RACChannel,而是使用RACChannelTo

RACChannelTo:使用这个宏要传入相关对象以及它的属性,比如RACChannelTo(view,backgroundColor),实际上创建了一个RACKVOChannel对象,在内部将其一端的leadingTerminalviewbackgroundColor属性进行绑定,并将其另一端followingTerminal暴露出来,也就是RACChannelTo的返回值,我们可以对followingTerminal进行订阅,拿到view. backgroundColor,同样followingTerminal发送信号也会同步到view.backgroundColor

用它来实现双向绑定,RACChannelTo(button,backgroundColor) =RACChannelTo(view,backgroundColor);buttonview的背景颜色进行绑定,两边相互影响,进行同步。


代码如下:

函数响应式编程(FRP)与 ReactiveCocoa

运行效果:

没有绑定前

函数响应式编程(FRP)与 ReactiveCocoa

绑定后:点击事件未触发

函数响应式编程(FRP)与 ReactiveCocoa

触发点击事件

函数响应式编程(FRP)与 ReactiveCocoa



 常用宏

RAC(TARGET, ...):给某个对象的某个属性进行绑定。

//当textfield开始编辑时,关闭button响应

RAC(_button,enabled) = [[self rac_signalForSelector:@selector(textFieldDidBeginEditing:) fromProtocol:@protocol(UITextFieldDelegate)] mapReplace:@NO];


RACObserve(TARGET, KEYPATH):KVO,监听某个对象的属性,返回的是信号。

函数响应式编程(FRP)与 ReactiveCocoa

RACChannelTo:用于双向绑定的一个通道终端。

函数响应式编程(FRP)与 ReactiveCocoa


RACTuplePack:将数据包装成RACTuple(元组)。

函数响应式编程(FRP)与 ReactiveCocoa


RACTupleUnpack(...):把元组解包成对应的数据

函数响应式编程(FRP)与 ReactiveCocoa


       demo

      https://github.com/kangxg/ThreadLock.git



 








 




相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-15
  • 2021-06-30
猜你喜欢
  • 2022-12-23
  • 2021-06-09
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-30
  • 2021-09-11
相关资源
相似解决方案