(整个关于ReactiveCocoa的工程可以在https://github.com/qianhongqiang/QHQReactive下载)

ReactiveCocoa的介绍我就不说了,可以自行百度。ReactiveCocoa这个框架目前来看很热门,但是不流行。归根到底,是学习成本太高,光看头文件,你几乎就根本不知道该如何使用。ReactiveCocoa内部实现大量使用了block,在block嵌套比较深的情况下,阅读源码也变得困难。我这里就给大家做个抽离,分解各个模块。因为我刚开始阅读时,我甚至于不知道该如何入手。源码解析如有错误,欢迎指正。

首先我先展示一段ReactiveCocoa的代码

```

  RACSignal *signal = [RACSignal createSignal:^(id subscriber) {
    [subscriber sendNext:[NSDate date]];
    [subscriber sendCompleted];
    return nil;
  }];
  [signal subscribeNext:^(id x) {
    NSLog(@"next:%@", x);
  } error:^(NSError *error) {
    NSLog(@"error:%@", error);
  } completed:^{
    NSLog(@"completed");
  }];
```
这段代码的作用是创建了一个型号,并且订阅这个型号。代码很优雅是不是?优雅的背后,总是需要大量的工作来支持。
现在我要重写个RAC,不过是个简易版本的,简易版本就是将主逻辑保留,细节处理掉过。这一节只实现上面的功能。
这里实现了两个类QHQSignal和QHQSubscriber
```

@interface QHQSignal ()

@property (nonatomic, copy) void (^didSubscriber)(id subscriber);

@property (nonatomic, strong) QHQSubscriber *scriber;

@end

@implementation QHQSignal

+(QHQSignal *)createSignal:(void (^)(id subscriber))didSubscriber {

QHQSignal *signal = [[self alloc] init];

signal.didSubscriber = didSubscriber;

return signal;

}

-(void)subscribeNext:(void (^)(id))nextBlock {

QHQSubscriber *scriber = [QHQSubscriber subscriberWithNextBlock:nextBlock];

self.scriber = scriber;

self.didSubscriber(self.scriber);

}

@end

```
```

@interface QHQSubscriber ()

@property (nonatomic, copy) void(^nextBlock)(id x);

@property (nonatomic, copy) void(^completionBlock)(id x);

@property (nonatomic, copy) void(^errorBlock)(id x);

@end

@implementation QHQSubscriber

+(instancetype)subscriberWithNextBlock:(void (^)(id x))nextBlock {

return [self subscriberWithNextBlock:nextBlock completionBlock:nil errorBlock:nil];

}

+(instancetype)subscriberWithNextBlock:(void (^)(id x))nextBlock completionBlock:(void (^)(id x))completionBlock errorBlock:(void (^)(id x))errorBlock {

QHQSubscriber *subscriber = [[QHQSubscriber alloc] init];

subscriber.nextBlock = nextBlock;

subscriber.completionBlock = completionBlock;

subscriber.errorBlock = errorBlock;

return subscriber;

}

-(void)sendNext:(id)next {

if (self.nextBlock) {

self.nextBlock(next);

}

}

@end

```
 
QHQSignal实现了一个创建方法,创建的时候需要将被订阅时执行的block传入,block有个subcriber参数,也就是信号的内部订阅者(为了rac实现的优雅,第一个比较让人困惑的设计),这个订阅者保存了真正订阅者,在订阅到信号的处理。打个比方,就是你告诉这个subcriber在信号来的时候,去干什么。
创建了信号之后,一旦有订阅者,也就是信号被subscribeNext(为了方便暂时不考虑compelete,与error)的时候,rac在内部创建了一个subscriber,并且这个subscriber保存了你的执行的block。subscriber其实相当于拿到了授权一样。
```

QHQSignal *demoSignal = [QHQSignal createSignal:^(id subscriber) {

[subscriber sendNext:@"1"];

}];

[demoSignal subscribeNext:^(id x) {

NSLog(@"%@",x);

}];

```
简简单单的就实现了如上的代码,是不是简单很多呢。一节写多了,看着容易吐,且看到这吧。

ReactiveCocoa源码拆分解析(一)的更多相关文章

  1. ReactiveCocoa源码拆分解析(二)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 上面抽丝剥茧的把最主要的信号机制给分离开了.但在RA ...

  2. ReactiveCocoa源码拆分解析(四)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 上一章节简要的说明了如何实现的热信号.但是像那么写, ...

  3. ReactiveCocoa源码拆分解析(七)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 在这篇博客中,我将把ReactiveCocoa中的擦 ...

  4. ReactiveCocoa源码拆分解析(六)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) RAC为了实现优雅的信号绑定,可谓使尽浑身解数,不仅 ...

  5. ReactiveCocoa源码拆分解析(五)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 好多天没写东西了,今天继续.主要讲解RAC如何于UI ...

  6. ReactiveCocoa源码拆分解析(三)

    (整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 这一章节主要讨论信号的“冷”与“热” 在RAC的世界 ...

  7. mybatis 3.x源码深度解析与最佳实践(最完整原创)

    mybatis 3.x源码深度解析与最佳实践 1 环境准备 1.1 mybatis介绍以及框架源码的学习目标 1.2 本系列源码解析的方式 1.3 环境搭建 1.4 从Hello World开始 2 ...

  8. spring源码深度解析— IOC 之 开启 bean 的加载

    概述 前面我们已经分析了spring对于xml配置文件的解析,将分析的信息组装成 BeanDefinition,并将其保存注册到相应的 BeanDefinitionRegistry 中.至此,Spri ...

  9. Spring框架之spring-web web源码完全解析

    Spring框架之spring-web web源码完全解析 spring-web是Spring webMVC的基础,由http.remoting.web三部分组成,核心为web模块.http模块封装了 ...

随机推荐

  1. C++ 第二次课堂作业(反转链表)

    题目链接: 传送门 GitHub链接: 传送门

  2. FZU 2193 So Hard (有限小数转换最简分数)(想法题)

    题目链接: 传送门 So Hard Time Limit: 1000MS     Memory Limit: 65536K 题目描述 请将有限小数化为最简分数. 输入 一个整数n 表示需要转化的小数个 ...

  3. 循序渐进 Jprofiler

    一 Jprofiler 1 什么是Jprofiler JProfiler是一个全功能的Java剖析工具(profiler),专用于分析J2SE和J2EE应用程式.它把CPU.线程和内存的剖析组合在一个 ...

  4. 网络存储(二)之ISCSI原理

    组成 一个简单ISCSI系统大致由以下部分构成 ISCSI Initiator 或者 ISCSI HBA ISCSI Target 以太网交换机 一台或者多台服务器 结构图如下: iscsi服务器用来 ...

  5. POJ2635The Embarrassed Cryptographer(大数取余+素数筛选+好题)

    题目链接 题意:K是由两个素数乘积,如果最小的素数小于L,输出BAD最小的素数,否则输出GOOD 分析 素数打表将 L 大点的素数打出来,一定要比L大,然后就开始枚举,只需K对 素数 取余 看看是否为 ...

  6. 探究JavaScript中的五种事件处理程序

    探究JavaScript中的五种事件处理程序 我们知道JavaScript与HTML之间的交互是通过事件实现的.事件最早是在IE3和Netscape Navigator 2中出现的,当时是作为分担服务 ...

  7. JAVA 自定义状态码

    返回信息类(ResponseInfo): public class ResponseInfo { public static final String Status = "status&qu ...

  8. Objective-C 中的类和对象

    http://blog.ibireme.com/2013/11/25/objc-object/ Objective-C的runtime是开源的,源码可以在苹果官网下载到:objc4. 在objc4-5 ...

  9. 开发板ping不通主机和虚拟机的看过来(转载)!

    前几天在做uboot下用tftp下载文件到开发板的实验时,为了能解决开发板ping不通主机和虚拟机的问题,可谓绞尽脑汁,正所谓久病成医,虽然为了这一小问题废了我那么长时间,但我在解决问题的同时也学到了 ...

  10. cookie和浏览器

    XHR API允许应用添加自定义的HTTP首部(通过setRequestHeader()方法),同时也有一些首部都是应用代码不能设定的. Accept-Charset.Accept-Encoding. ...