1:RACSingle 需要订阅信号

     RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
[subscriber sendNext:@""];
[subscriber sendCompleted];
return nil;
}]; [signal subscribeNext:^(id x) { } error:^(NSError * _Nullable error) { } completed:^{ }];
/************* 对应的源码 **************/
// 生成RACDynamicSignal。即生成RACSignal的子类
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
return [RACDynamicSignal createSignal:didSubscribe];
} // 在子类中保存 didSubscribe block, 每一次订阅都会执行
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
} /// 在订阅时执行保存在RACDynamicSignal中的didSubscribe block
- (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;
} // 生成订阅者。并调用RACDynamicSignal中的订阅方法,执行didSubscribe block
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL); RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
} // 生成的订阅者中保存 nextBlock, errorBlock, completedBlock.
+ (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;
} // 当订阅者收到sendNext方法时,就会执行nextBlock
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return; nextBlock(value);
}
}

2 RACSubject 既能订阅信号又能发送信号。 必须先订阅在发送。不然由于在sendNext时还没有订阅者会无法触发。

    /// 事例
RACSubject *sub = [[RACSubject alloc] init];
[sub subscribeNext:^(id _Nullable x) {
NSLog(@"%@", a);
}]; [sub sendNext:@"a"];
 //调用时和RACSignal有区别的方法
// 使用 subscribers 保存 订阅者。(RACDynamicSignal 还要执行didSubscrbe Block)
- (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];
} [disposable addDisposable:[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];
}
}]]; return disposable;
} // 找到需要的订阅者
- (void)enumerateSubscribersUsingBlock:(void (^)(id<RACSubscriber> subscriber))block {
NSArray *subscribers;
@synchronized (self.subscribers) {
subscribers = [self.subscribers copy];
} for (id<RACSubscriber> subscriber in subscribers) {
block(subscriber);
}
} // 这行nextBlock。
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];
}];
}

3 bind bind是RAC中map,merge, flatten, flattenMap的基础

flattenMap 实际上就是调用bind。 经过flattenMap映射后,subscribe的是block(value)即block里面的信号

  map 调用的flattenMap 经过Map映射后 subscribe的是[self return:block(value)]的信号假定为wrapSignal.而不是block(value)的信号假定为子信号。

flatten 调用的是flattenMap,subscribe的子信号。调用flatten订阅到的值必须是一个Signal。

     RACSignal *returnSig = [RACSignal return:@""];
RACSignal *bindSig = [returnSig bind:^RACSignalBindBlock {
return ^RACSignal * (id value, BOOL *bl) {
return [RACSignal return:value];
};
}]; [bindSig subscribeNext:^(id _Nullable x) {
NSLog(@"%@", x);
}];
/*
* -bind: should:
* 订阅原始信号,并将订阅到的原始信号值,赋值给binding block。如果binding block返回了新的信号。订阅它, 之后用生成的中转信号的订阅者,执行返回的信号的sendNext方法和 sendComplete方法
* 1. Subscribe to the original signal of values.
* 2. Any time the original signal sends a value, transform it using the binding block.
* 3. If the binding block returns a signal, subscribe to it, and pass all of its values through to the subscriber as they're received.
* 4. If the binding block asks the bind to terminate, complete the _original_ signal.
* 5. When _all_ signals complete, send completed to the subscriber.
*
* If any signal sends an error at any point, send that to the subscriber.
*/ /*
- (RACSignal *)bind:(RACSignalBindBlock (^)(void))block {
NSCParameterAssert(block != NULL); return [[RACSignal createSignal:^(id<RACSubscriber> subscriber) {
RACSignalBindBlock bindingBlock = block(); __block volatile int32_t signalCount = 1; // indicates self RACCompoundDisposable *compoundDisposable = [RACCompoundDisposable compoundDisposable]; void (^completeSignal)(RACDisposable *) = ^(RACDisposable *finishedDisposable) {
if (OSAtomicDecrement32Barrier(&signalCount) == 0) {
[subscriber sendCompleted];
[compoundDisposable dispose];
} else {
[compoundDisposable removeDisposable:finishedDisposable];
}
};
// signal 是bindingBlock返回的信号。订阅这个信号。由于在Block中有这个信号的sendNext方法故会直接执行他。之后接收到的值发送出去。
void (^addSignal)(RACSignal *) = ^(RACSignal *signal) {
OSAtomicIncrement32Barrier(&signalCount); RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init];
[compoundDisposable addDisposable:selfDisposable]; RACDisposable *disposable = [signal subscribeNext:^(id x) {
[subscriber sendNext:x];
} error:^(NSError *error) {
[compoundDisposable dispose];
[subscriber sendError:error];
} completed:^{
@autoreleasepool {
completeSignal(selfDisposable);
}
}]; selfDisposable.disposable = disposable;
}; @autoreleasepool {
RACSerialDisposable *selfDisposable = [[RACSerialDisposable alloc] init];
[compoundDisposable addDisposable:selfDisposable];
// 订阅初始的信号(上面的returnSig), 执行bindingBLock,
RACDisposable *bindingDisposable = [self subscribeNext:^(id x) {
// Manually check disposal to handle synchronous errors.
if (compoundDisposable.disposed) return; BOOL stop = NO;
id signal = bindingBlock(x, &stop); @autoreleasepool {
if (signal != nil) addSignal(signal);
if (signal == nil || stop) {
[selfDisposable dispose];
completeSignal(selfDisposable);
}
}
} error:^(NSError *error) {
[compoundDisposable dispose];
[subscriber sendError:error];
} completed:^{
@autoreleasepool {
completeSignal(selfDisposable);
}
}]; selfDisposable.disposable = bindingDisposable;
} return compoundDisposable;
}] setNameWithFormat:@"[%@] -bind:", self.name];
} */

ReactiveCocoa 源码阅读记录。的更多相关文章

  1. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

  2. flutter_boot android和flutter源码阅读记录

    版本号0.1.54 看源码之前,我先去看下官方文档,对于其源码的设计说明,文中所说的原生都是指android 看完官方文档的说明,我有以下几个疑问 第一个:容器是怎么设计的? 第二个:native和f ...

  3. Vue2.x 响应式部分源码阅读记录

    之前也用了一段时间Vue,对其用法也较为熟练了,但是对各种用法和各种api使用都是只知其然而不知其所以然.最近利用空闲时间尝试的去看看Vue的源码,以便更了解其具体原理实现,跟着学习学习. Proxy ...

  4. underscore源码阅读记录

    这几天有大神推荐读underscore源码,趁着项目测试的空白时间,看了一下. 整个underscore包括了常用的工具函数,下面以1.3.3源码为例分析一下. _.size = function(o ...

  5. Linux内核源码阅读记录一之分析存储在不同段中的函数调用过程

    在写驱动的过程中,对于入口函数与出口函数我们会用一句话来修饰他们:module_init与module_exit,那会什么经过修饰后,内核就能狗调用我们编写的入口函数与出口函数呢?下面就来分析内核调用 ...

  6. JQuery源码阅读记录

    新建html文件,在浏览器中打开文件,在控制台输入consoole.log(window);新建html文件,引入JQuery后在浏览器中打开,在控制台同样输入consoole.log(window) ...

  7. vue 源码阅读记录

    0.webpack默认引入的是vue.runtime.common.js,并不是vue.js,功能有略微差别,不影响使用 1.阅读由ts编译后的js: 入口>构造函数 >定义各类方法 &g ...

  8. underscore源码阅读记录(二)

    引自underscore.js context参数用法 _.each(list, iteratee, [context]); context为上下文,如果传递了context参数,则把iterator ...

  9. RIPS源码阅读记录(二)

    Author: tr1ple 这部分主要分析scanner.php的逻辑,在token流重构完成后,此时ini_get是否包含auto_prepend_file或者auto_append_file 取 ...

随机推荐

  1. NOIP水题测试(2017082501)

    日常水题测试又来了! 以后答案都以单题形式公布. 下面看今天的水题: 时间限制:5小时 题目一:无法形容的水 题目二:比上一题还水 题目三:一元三次方程求解 题目四:单词接龙 题目五:统计单词个数 题 ...

  2. 20155312 2006-2007-2 《Java程序设计》第六周学习总结

    20155312 2006-2007-2 <Java程序设计>第六周学习总结 课堂笔记 学习进程 周一看视频-2h 周二以代码为中心看书-3h 课后选择题-5h 教材指导 应试 Linux ...

  3. Seaborn图形可视化库

    一.绘图 1)快速生成图 import numpy as np import matplotlib.pyplot as plt def sinplot(filp=): x = np.linspace( ...

  4. 63.delegate回调 和block回调

    效果:viewController里面放置一个按钮和Lab,点击按钮进入oneViewController(delegate回调)或者BlockViewController(block回调),两者控制 ...

  5. 2018.11.17 codechef PRIMEDST(点分治+fft)

    传送门 fftfftfft一眼题(其实最先想到的是nttnttntt,wawawa了几次之后发现模数不够大果断弃疗写fftfftfft) 我们点分治统计答案的个数. 考虑现在已经统计出了到当前点的所有 ...

  6. systemC的环境搭建

    window下systemc的环境搭建 安装视频 一.编译SystemC库 1.下载SystemC library source code (systemc-2.3.1版本) 2.解压到工作目录 3. ...

  7. python的6种基本数据类型--字典

    python的6种基本数据类型--字典   字典 字典的定义与特性 字典是Python语言中唯一的映射类型. 定义:{key1:value1,key2:value2} 1.键与值用冒号":& ...

  8. TensorFlow 实现 RNN 入门教程

    转子:https://www.leiphone.com/news/201705/zW49Eo8YfYu9K03J.html 最近在看RNN模型,为简单起见,本篇就以简单的二进制序列作为训练数据,而不实 ...

  9. 如何悄悄地提升MySQL用户权限

    温馨提示: 一次成功的非法提权,需要的必备条件是:1.对mysql权限表的查.改权限: 2.一次不经意的数据库服务器重启: 此次测试版本:5.6.25 准备邪恶用户: grant update on ...

  10. 20155205《Java程序设计》实验五(网络编程与安全)实验报告

    20155205 <Java程序设计>实验五(网络编程与安全)实验报告 一.实验内容及步骤 (一) 两人一组结对编程 参考http://www.cnblogs.com/rocedu/p/6 ...