博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ReactiveCocoa源码拆分解析(一)
阅读量:6798 次
发布时间:2019-06-26

本文共 2657 字,大约阅读时间需要 8 分钟。

(整个关于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);

    }];

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

转载于:https://www.cnblogs.com/qianhongqiang/p/5056137.html

你可能感兴趣的文章
C#中类的概念
查看>>
Primary key、unique、index之间的关系
查看>>
关于完美的练习
查看>>
heap&stack 区别
查看>>
hadoop hive安装手记(转)
查看>>
kinect新知
查看>>
堆实例
查看>>
ASP.NET中各个后缀名的含义
查看>>
always和always@(*)
查看>>
Android 中压力测试工具Monkey的用法(转)
查看>>
NYOJ-61 传纸条(一)
查看>>
乱码问题总结
查看>>
Raspberry pi raspbain系统下使用vim
查看>>
进程通信之共享内存
查看>>
通用单例模式
查看>>
Sharepoint学习笔记—习题系列--70-576习题解析 -(Q99-Q101)
查看>>
使用js 文件参数 以及IHttpModule实现服务验证asp.net 版的初步实现
查看>>
JavaScript操作Cookie
查看>>
转oracle 学习 - 表空间
查看>>
百度地图显示多个标注点
查看>>