先预习一下Block
- Block
inlineBlock```
<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
<#statements#>
};```
/**
* Block : ARC strong 使用strong就可以 但是非ARC就用copy
*/
@property (nonatomic, copy) void(^JYFBlock)();```
// 1.对象里面包含一个属性 Block作为对象的属性
self.p = [[Person alloc] init];
// Block --inlineBlock
void(^JYFBlock)() = ^() {
NSLog(@"发哥");
};
self.p.JYFBlock = JYFBlock;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.p.JYFBlock();
}
- 作为参数传递
- (void)eat:(void(^)(NSString *))block;```
- (void)eat:(void (^)(NSString *))block{
block(@"香蕉");
}
// 作为参数传递
self.p = [[Person alloc] init];
[self.p eat:^(NSString *value){
NSLog(@"%@", value);
}];```
// 只要有返回值的方法 我们都可以使用点语法 那么Get方法之所以能点 就是因为有返回值
- Block作为返回值(扩展非常强!!!)
// 定义一个能够返回Block的Run方法
- (void(^)(int))run;```
- (void (^)(int))run{
return ^(int m){
NSLog(@"哥们跑起来了 跑了%d",m);
};
}
self.p = [[Person alloc] init];
//p.run(3)
self.p.run(100);```
###RAC
- ReactiveCocoa(RAC) Github上的一个开源框架
- RAC有什么用呢?
1: 帮助我们更简单霸气地处理事件
2: 函数响应编程框架
- 1: RACSignal:信号类!通过它创建一个信号
2:通过订阅者订阅刚刚的信号!(变成:热信号)
3:发送信号
RACSignal:信号类 当我们有数据产生的时候 我们就创建一个信号 这个Block需要一个返回值
// 1. 创建信号(冷信号!)
// 被订阅 就会调用
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 3:发送信号subscriber
[subscriber sendNext:@"呵呵哈哈嘿嘿额"];
return nil;
}];
// 2. 订阅信号(热信号!!)
// 发动的时候才会调用
// 处理数据 展示UI界面
[signal subscribeNext:^(id x) {
// 订阅信号
// x: 信号发送的内容!!
NSLog(@"%@",x);
}];
- RAC原理
1:创建信号RACSignal,底层保存信号Block
- (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
2:订阅信号 先创建一个订阅者(RACSubscriber) 然后才去订阅信号 保存了订阅者nextBlock
-
(RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}```
- 执行didSubscriber
- 执行的时候 干了什么事情???
- 即走进了之前的保存的Block 即发送数据
- 发送消息 做了什么??
从源码来看 终于调用了block 那么订阅者接收到了信息
#pragma mark RACSubscriber
- (void)sendNext:(id)value {
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
}```
###流程图
![Paste_Image.png](https://img.haomeiwen.com/i189984/6114db92e3f5ad7f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
###RACDisposable
它可以帮助我们取消订阅,信号发送完毕了,或者失败了,我们都要取消订阅,就像我们注册通知,取消通知一样的道理。
// RACSignal:信号类 当我们有数据产生的时候 我们就创建一个信号 这个Block需要一个返回值
// 1. 创建信号(冷信号!)
// 被订阅 就会调用
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 3:发送信号subscriber 默认一个信号发送完毕 就会取消完毕
[subscriber sendNext:@"呵呵哈哈嘿嘿额"];
return [RACDisposable disposableWithBlock:^{
// 只要信号取消订阅 就回来这里
// 为什么会来这里呢?因为消息发送完毕之后 sub就没了
// 清空资源
NSLog(@"哥们取消订阅了");
}];
}];
// 2. 订阅信号(热信号!!)
// 发动的时候才会调用
// 处理数据 展示UI界面
RACDisposable *disposable = [signal subscribeNext:^(id x) {
// 订阅信号
// x: 信号发送的内容!!
NSLog(@"%@",x);
}];
// 手动取消订阅
[disposable dispose];
###RACSubject:信号提供者!!自己可以充当信号,又能够发送信号
//1:创建信号
RACSubject *subject = [RACSubject subject];
// 2:订阅信号
[subject subscribeNext:^(id x) {
NSLog(@"接收到了数据%@",x);
}];
// 3: 发送信号
[subject sendNext:@"汉堡包"];```
Paste_Image.png
- 由上图可以看出 之所以RACSubject拥有这么多功能,是因为它使用继承Signal+遵守Subscriber协议。
- 来看一下生命周期
#pragma mark Lifecycle
+ (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;
}
- (void)dealloc {
[self.disposable dispose];
}
- 可以看出来,这些代码 对RACSubject的生命周期,进行了一个维护。
1:创建信号(RACSubject)就是创建了一个可变数组,就是我们的Subscribers
- (id)init {
self = [super init];
if (self == nil) return nil;
_disposable = [RACCompoundDisposable compoundDisposable];
_subscribers = [[NSMutableArray alloc] initWithCapacity:1];
return self;
}
2:订阅信号
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
return [self subscribe:o];
}```
![Paste_Image.png](https://img.haomeiwen.com/i189984/b90cbb851466b49d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
-
(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];
}
}];
}
3:发送数据 遍历订阅者对象执行 遍历发送
![Paste_Image.png](https://img.haomeiwen.com/i189984/c396716d22f50cab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
-
(void)enumerateSubscribersUsingBlock:(void (^)(id<RACSubscriber> subscriber))block {
NSArray *subscribers;
@synchronized (self.subscribers) {
subscribers = [self.subscribers copy];
}for (id<RACSubscriber> subscriber in subscribers) {
block(subscriber);
}
}
pragma mark RACSubscriber
- (void)sendNext:(id)value {
[self enumerateSubscribersUsingBlock:^(id<RACSubscriber> subscriber) {
[subscriber sendNext:value];
}];
}```
网友评论