RAC的函数式编程

来源:互联网 发布:设置windows在文件夹 编辑:程序博客网 时间:2024/06/05 22:30

####为什么是函数式

  • 数据与函数是松耦合的
  • 函数隐藏了它们的实现,语言的抽象是函数,以及将函数组合起来表达。
  • 核心抽象模型是函数,不是数据结构
  • 核心活动是编写新的函数。
  • 变量缺省是不变的,减少可变性变量的使用,并发性好

####函数式的实现objc语言使用block实现函数式编程,在典型的函数式编程框架RAC中,把数据的生成和数据的处理单独的放在block中处理,数据的生产和消费之间是松耦合的,block是数据处理的最小单位。

本文使用的是Objc版本的ReactiveCocoa,创建一个Objc的项目,使用pod导入:

pod 'ReactiveObjC', '3.0.0'

####创建RACSignal以及订阅这个RACSignal接收消息
简单的代码如下

RACSignal* signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {    [subscriber sendNext:@"message"];    return nil;}];[signal subscribeNext:^(id  _Nullable x) {    NSLog(@"received:%@", x);}];// 控制台输出2017-04-24 17:36:49.364 EffectiveOCDemo[46385:2426010] received:message

####RACSignal对象创建

// RACSignal.m+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {return [RACDynamicSignal createSignal:didSubscribe];}// RACDynamicSignal.m+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {RACDynamicSignal *signal = [[self alloc] init];signal->_didSubscribe = [didSubscribe copy];return [signal setNameWithFormat:@"+createSignal:"];}

使用RACSignal类的类方法createSignal创建一个RACSignal最终创建的是一个RACSignal的子类RACDynamicSignal的对象,对象中会把参数中的didSubscribe block 保存到_didSubscribe实例变量中,后面发送消息的时候回用到_didSubscribe这个block。

####subscribeNext 方法

// RACSignal.m- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {NSCParameterAssert(nextBlock != NULL);RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];return [self subscribe:o];}// RACSubscriber.m 快捷方法创建RACSubscriber对象+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {RACSubscriber *subscriber = [[self alloc] init];subscriber->_next = [next copy];subscriber->_error = [error copy];subscriber->_completed = [completed copy];return subscriber;}// RACDynamicSignal.m - (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {NSCParameterAssert(subscriber != nil);RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];if (self.didSubscribe != NULL) {RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{RACDisposable *innerDisposable = self.didSubscribe(subscriber);[disposable addDisposable:innerDisposable];}];[disposable addDisposable:schedulingDisposable];}return disposable;}

RACSignal的subscribeNext方法中会创建了一个sub,_next成员变量用于保存参数中的nextBlock,后面接收消息的时候会用到_next block。创建了RACSubscriber对象之后,调用RACDynamicSignal对象的的subscribe方法,并且把RACSubscriber对象当做参数进行传递。然后执行之前保存的didSubscribe block

self.didSubscribe(subscriber);

也就是执行了下面这个block,在这个block中又会执行RACSubscriber的sendNext方法

RACSignal* signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {    [subscriber sendNext:@"message"];    return nil;}];

####sendNext方法

- (void)sendNext:(id)value {@synchronized (self) {void (^nextBlock)(id) = [self.next copy];if (nextBlock == nil) return;nextBlock(value);}}

sendNext方法会同步取出之前保存的next block,然后执行该block,并且传递sendNext方法中的参数,执行nextblock也就是执行了下面这个block

[signal subscribeNext:^(id  _Nullable x) {    NSLog(@"received:%@", x);}];

这样一个完整的消息发送接收链就创建起来了,在RACSignal createSignal block中发送的数据在signal subscribeNext block中可以同步的接收到。

####小结#####冷信号和热信号

RACSignal* signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {    [subscriber sendNext:@"message"];    return nil;}];

创建的RACSignal对象里面的_didSubscribe并不会自动执行,这种RACSignal成为_冷信号,当且仅当调用了subscribeNext订阅这个信号,RACSignal对象 的_didSubscribe才会得到执行,这样RACSignal成为了热信号_,在_didSubscribe block执行的时候同时会调用RACSubscriber sendNext方法,sendNext又会调用RACSubscriber的nextBlock,这样消息转发完毕。

#####RACSignal数据流图RACSignal数据流图

原创粉丝点击