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数据流图
- RAC的函数式编程
- ReactiveCocoa RAC 响应式函数编程(FRP)
- RAC、响应式编程的学习
- RAC 响应式编程
- RAC响应式编程初探
- IOS响应式编程框架ReactiveCocoa(RAC)
- iOS响应式编程框架ReactiveCocoa(RAC)
- 函数式编程的内建函数
- 函数式编程的优点
- 函数式编程的思想
- 函数式编程的杂七杂八
- 函数式编程的优点
- Swift的函数式编程( ) -> ( )
- Swift 的函数式编程
- Swift 的函数式编程
- 火热的函数式编程
- 函数式编程的好处
- Spark的函数式编程
- IOS 使用 WKWebView 加载本地的JS和CSS文件出现乱码问题
- 关于 mybatis 中Type handler was null on parameter mapping for property '__frch_id_0'类似的错误
- 最实用的表头制作技巧,都在这了
- 相机标定原理介绍(一)
- 发布自己的CocoaPods库
- RAC的函数式编程
- Excel快捷键大全
- Objective-C KVO 中 runtime 探究
- 在jsp页面/input显示当前时间(初始换时间格式)
- IOS 数据库升级数据迁移解决方案
- 机器学习实战2-运行KNN示例
- codevs 2218 补丁vs错误(状压搜索)(luogu P1527)
- IOS 工厂模式的面向协议编程思想
- UITableViewCell使用自动布局的“最佳实践”