RAC初窥

作者: 952625a28d0d | 来源:发表于2017-04-21 00:31 被阅读59次

先预习一下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];
    }```

Paste_Image.png
  • 执行didSubscriber
Paste_Image.png
  • 执行的时候 干了什么事情???
  • 即走进了之前的保存的Block 即发送数据
Paste_Image.png Paste_Image.png
  • 发送消息 做了什么??

从源码来看 终于调用了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];
    }];
    }```

相关文章

  • RAC初窥

    先预习一下Block Block <#returnType#>(^<#blockName#>)(<#paramet...

  • 初窥

    初窥世界的美好 白的风 白的肌肤 和盈盈一握的腰肢 在你的头发里 有一个蓝色大海的梦 蓝的帆船和蓝的浪花 自然是美...

  • 初窥

    这个积分管理项目已经到收尾的阶段了,感受良多。 对于错误处理这方面这周我的规划也更为清楚一些了。明天如果能够预期结...

  • 初认RAC

    ReactiveCocoa的核心: 信号,没错就是信号,发了信号要干嘛干嘛,讲白了就是一个事件流; 那么我们来把这...

  • 初窥南京

    古鸡鸣寺门外,一条长满爬山虎的墙。 城墙下的绿植。 1912街区,没有什么能过阻挡,我对自由的向往。 午后墙壁上斑...

  • 初窥HTTP

    要知道HTTP肯定要先知道WWW,下面我用思维导图来介绍下: 1,弄懂了上图的关系,接下来着重介绍HTTP。 先介...

  • 初窥Scrapy

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘,信息处理或存储历史数据...

  • mongodb初窥

    启动MongoDB服务:在 MongoDB 安装目录的 bin 目录下执行mongod show dbs -- 显...

  • RxSwift初窥

    前言 很久一段时间没写博客了,一方面是自己各种事情折腾,二是新项目开始用Swift了,边学边做忙死了,现在终于快忙...

  • block初窥

    一.block的简单使用 1.block声明 block变量的声明格式为: 返回值类型 (^block名字)(参数...

网友评论

      本文标题:RAC初窥

      本文链接:https://www.haomeiwen.com/subject/iphxzttx.html