ReactiveCocoa源码解读(一)
本着饮水思源的想法,面对 本文主要从 一、RACSignal1. 应用// 1.创建信号
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id subscriber) {
// 注:block在此仅仅是个参数,未被调用,
//当有订阅者订阅信号时会调用block。
// 2.发送信号
[subscriber sendNext:@1];
// 如果不在发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
return nil;
}];
// 3.订阅信号,才会激活信号.
[siganl subscribeNext:^(id x) {
// block调用时刻:每当有信号发出数据,就会调用block.
NSLog(@"接收到数据:%@",x);
}];
2.源码实现
// RACDynamicSignal.m
+ (RACSignal *)createSignal:(RACDisposable * (^)(id subscriber))didSubscribe {
//创建了一个RACDynamicSignal类的信号
RACDynamicSignal *signal = [[self alloc] init];
//将代码块保存到信号里面(但此时仅仅是保存,没有调用),所以信号还是冷信号
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
(RACDisposable *)subscribeNext:(void (^ )(id x))nextBlock;
// RACSignal.m
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
// 内部创建了RACSubscriber(订阅者)类的实例对象o,并且将nextBlock保存到o中,在返回值出执行o,实际也是执行了nextBlock。
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
// RACSubscriber.m
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
RACSubscriber *subscriber = [[self alloc] init];
// 将block保存到subscriber中
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];
//判断有无self.didSubscribe,有则执行该self.didSubscribe,意味着将订阅者subscriber发送过去
if (self.didSubscribe != NULL) {
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
// RACPassthroughSubscriber.m
- (instancetype)initWithSubscriber:(id)subscriber signal:(RACSignal *)signal disposable:(RACCompoundDisposable *)disposable {
NSCParameterAssert(subscriber != nil);
self = [super init];
if (self == nil) return nil;
// 保存订阅者,信号,处理操作
_innerSubscriber = subscriber;
_signal = signal;
_disposable = disposable;
[self.innerSubscriber didSubscribeWithDisposable:self.disposable];
return self;
}
[subscriber sendNext:@1]
// RACPassthroughSubscriber.m
- (void)sendNext:(id)value {
if (self.disposable.disposed) return;
if (RACSIGNAL_NEXT_ENABLED()) {
RACSIGNAL_NEXT(cleanedSignalDescription(self.signal),cleanedDTraceString(self.innerSubscriber.description),cleanedDTraceString([value description]));
}
[self.innerSubscriber sendNext:value];
}
// RACSubscriber.m
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
// 名为next的block是返回值为void,参数为id类型的value,在sendNext:内部,将next复制给nextBlock,执行该方法后,subscribeNext:的block参数才会被调用。
nextBlock(value);
}
}
3.流程图4.总结先创建信号,然后订阅信号,最后执行didSubscribe内部的方法,顺序是不能变的 RACSignal底层实现 * 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
* 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
2.1 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
2.2 subscribeNext内部会调用siganl的didSubscribe
* 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
3.1 sendNext底层其实就是执行subscriber的nextBlock
二、RACSubject1. 应用// 创建信号
RACSubject *subject = [RACSubject subject];
// 订阅
[subject subscribeNext:^(id x) {
NSLog(@"第一个订阅者:%@",x);
}];
// 发送信号
[subject sendNext:@"1"];
2.源码实现
// RACSubject.m
+ (instancetype)subject {
return [[self alloc] init];
}
- (id)init {
self = [super init];
if (self == nil) return nil;
_disposable = [RACCompoundDisposable compoundDisposable];
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
return self;
}
RACSubject订阅信号的实质就是将内部创建的订阅者保存在订阅者数组self.subscribers中,仅此而已。订阅者对象有一个名为nextBlock的block参数 // 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
+ (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;
}
// RACSubject.m
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
NSMutableArray *subscribers = self.subscribers;
@synchronized (subscribers) {
[subscribers addObject:subscriber];
}
return [RACDisposable disposableWithBlock:^{
@synchronized (subscribers) {
// Since newer subscribers are generally shorter-lived,search
// starting from the end of the list.
NSUInteger index = [subscribers indexOfObjectWithOptions:NSEnumerationReverse passingTest:^ BOOL (id<RACSubscriber> obj,NSUInteger index,BOOL *stop) {
return obj == subscriber;
}];
if (index != NSNotFound) [subscribers removeObjectAtIndex:index];
}
}];
}
底层实现:
1. 先遍历订阅者数组中的订阅者;
2. 后执行订阅者中的nextBlock;
3. 最后让订阅者发送信号
// RACSubject.m
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id subscriber) {
[subscriber sendNext:value];
}];
}
- (void)enumerateSubscribersUsingBlock:(void (^)(id subscriber))block {
NSArray *subscribers;
@synchronized (self.subscribers) {
subscribers = [self.subscribers copy];
}
for (id subscriber in subscribers) {
block(subscriber);
}
}
3.流程图4.总结
RACSubject的底层与RACSignal不一样:
必须先订阅,后发送信息。订阅信号就是创建订阅者的过程,如果不先订阅,数组中就没有订阅者对象,那就通过订阅者发送消息 三、RACReplaySubject1.应用
RACReplaySubject *subject = [RACReplaySubject subject];
// 第一次订阅
[subject subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
// 发送信号
[subject sendNext:@"1"];
// 第一次订阅
[subject subscribeNext:^(id x) {
NSLog(@"%@",x);
}];
2.源码实现
// RACSubject.m
+ (instancetype)subject {
return [[self alloc] init];
}
// RACReplaySubject.m
- (instancetype)init {
return [self initWithCapacity:RACReplaySubjectUnlimitedCapacity];
}
- (instancetype)initWithCapacity:(NSUInteger)capacity {
self = [super init];
if (self == nil) return nil;
_capacity = capacity;
// 会用这个数组保存值value
_valuesReceived = (capacity == RACReplaySubjectUnlimitedCapacity ? [NSMutableArray array] : [NSMutableArray arrayWithCapacity:capacity]);
return self;
}
// RACSignal.m
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}
// RACReplaySubject.m
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable];
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
@synchronized (self) {
for (id value in self.valuesReceived) {
if (compoundDisposable.disposed) return;
[subscriber sendNext:(value == RACTupleNil.tupleNil ? nil : value)];
}
if (compoundDisposable.disposed) return;
if (self.hasCompleted) {
[subscriber sendCompleted];
} else if (self.hasError) {
[subscriber sendError:self.error];
} else {
RACDisposable *subscriptionDisposable = [super subscribe:subscriber];
[compoundDisposable addDisposable:subscriptionDisposable];
}
}
}];
[compoundDisposable addDisposable:schedulingDisposable];
return compoundDisposable;
}
// RACReplaySubject.m
- (void)sendNext:(id)value {
@synchronized (self) {
//重点:发送信号的时候,会先将值value保存到数组中
[self.valuesReceived addObject:value ?: RACTupleNil.tupleNil];
//调用父类发送(先遍历订阅者,然后发送值value)
[super sendNext:value];
if (self.capacity != RACReplaySubjectUnlimitedCapacity && self.valuesReceived.count > self.capacity) {
[self.valuesReceived removeObjectsInRange:NSMakeRange(0,self.valuesReceived.count - self.capacity)];
}
}
}
3.原理图4.总结
未完待续 ……(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |