####为什么是函数式
- 数据与函数是松耦合的
- 函数隐藏了它们的实现,语言的抽象是函数,以及将函数组合起来表达。
- 核心抽象模型是函数,不是数据结构
- 核心活动是编写新的函数。
- 变量缺省是不变的,减少可变性变量的使用,并发性好
####函数式的实现 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数据流图