RAC的函数式编程

####为什么是函数式

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

####函数式的实现 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数据流图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值