美学原理RAC基础学习一:信号和订阅者模式

俺们当知情到RAC的强以及不可思议的时段,需要思考两单地方:1、它是什么贯彻的?第二独问题虽另行起难度:2、它是哪想到这样设计之?
此处我们先行品尝研究第一个问题,它是什么样落实的,分析主要的条。

于RAC里面,我们拥有围绕的物就主体是即刻几类:信号(signal)、订阅者(subscriber)、还有关于信号的劳动者实体、信号的顾客,这几个之关系。
咱俩怎么采取RAC,因为它解耦太好了,除此之外,它简洁,配合MVVM能达出特别非常之意图等等。相信我们都写腻了靶之间的复杂性通信、一老大堆状态的缔造与治本、越来越难保障的事务逻辑,这些虽是RAC诞生的重任。

初家总是容易受同一堆概念来得晕头转向,我怀念其实只有是这几种:

RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber){
            [subscriber sendNext:@(1)];
            [subscriber sendCompleted];
            return nil;
        }];

  1、createSignal好难啊;2、subscriber是啊?3、这个block什么时候调用?

[signal subscribeNext:^(id x) {
        if ([x boolValue]) {
            _navView.hidden = YES;
        } else {
            _navView.hidden = NO;
            [UIView animateWithDuration:.5 animations:^{
                _navView.alpha = 1;
            }];
        }
    }];

  4、subscribeNext又是什么?5、这个block什么时调用?

  6、看起上面两截代码来关联,但是实际怎么打算的?

叫咱们事先来缓解者的迷离吧!

首先部分 订阅者和信号##\

  1、隐藏的订阅者

  平时我们打交道的便是信号,但是连说订阅,却休了解订阅到底是什么进展的,也束手无策解答者的问题,让咱们根据源码分析一下订阅过程。

  首先来认识一个靶:订阅者(RACSubscriber)。
订阅者订阅信号,就是这般简单的等同桩业务。只不过框架隐藏了这目标,我们吧无必要和订阅者打交道,只待报告信号一致码业务,那便是设发送了数额(三种植事件:next、complete、error),我们用开呀事情(类似回调的定义)。

  第一步是创立信号,看一下地方的首先段子代码,createSignal类方法:
此而说一下,信号RACSignal有部分子类,我们经常因此之是RACDynamicSignal和RACSubject,先不睬RACSubject。createSignal类方法创建的即是RACDynamicSignal对象。

-----RACDynamicSignal.h-----
@property (nonatomic, copy, readonly) RACDisposable * (^didSubscribe)(id<RACSubscriber> subscriber);

-----RACSignal.m-----
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    return [RACDynamicSignal createSignal:didSubscribe];
}

-----RACDynamicSignal.m-----
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
    return [signal setNameWithFormat:@"+createSignal:"];
}

  我们可窥见,RACDynamicSignal有一个性,名字叫didSubscribe的block对象。createSignal方法传递的block参数,就是赋值给didSubscribe属性。
  对于问题1,我们可以少这么回,createSignal的意思是,创建一个signal对象,并且将参数赋值给signal的名叫吧didSubscribe的特性,这个block的参数是subscriber,返回RACDisposable。

  第二步是订阅信号,看一下次之段子代码subscribeNext:

-----RACSubscriber.m-----
@property (nonatomic, copy) void (^next)(id value);

-----RACSignal.m-----
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
    NSCParameterAssert(nextBlock != NULL);

    RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
    return [self subscribe:o];
}

-----RACDynamicSignal.m-----

- (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;
}

  我们可见到,subscribeNext方法第一步是创立了一个RACSubscriber,也尽管是开创了一个订阅者,而且将subscribeNext的参数传递给RACSubscriber对象,RACSubscriber会把参数赋值给协调一个叫也next的Block类型的习性,此处,我们得对上面第4独问题,subscribeNext方法创建一个订阅者,并且把block参数,传递让订阅者一个名被next的习性,block参数接收的凡id类型,返回的是RACDisposable对象。连接下去执行[self
subscribe:o],也不怕是订阅操作。我们于探订阅方法subscribe的贯彻:上面的代码很鲜明,直接是self.didSubscribe(subscriber),我们得以了解,刚刚创建的subscriber对象,直接传送让上文中我们干的signal的didSubscribe属性。这般,我们得以说明上面的亚独与老三个问题,subscriber就是didSubscribe的形参,block对象是在subscribeNext的当儿实施之,刚刚的订阅者对象作为参数传入,就是subscriber对象。

  那么createSignal方法中,[subscriber sendNext:@(1)]是呀意思呢?
  看一下sendNext方法吧:

- (void)sendNext:(id)value {
    @synchronized (self) {
        void (^nextBlock)(id) = [self.next copy];
        if (nextBlock == nil) return;

        nextBlock(value);
    }
}

  我们可窥见,sendNext的贯彻,也就是是直接实施及文中的nextBlock。为即是答复了上面第五独问题。

  总结一下,signal持有didSubscribe参数(createSignal传上的可怜block),subscriber持有nextBlock(就是subscribeNext传进的很block),当尽[signal
subscribe:subscriber]的时刻,signal的didSubscribe执行,内部发生subscriber
sendNext的调用,触发了subscriber的nextBlock的调用。到这边,我们基本将信号和订阅者,以及订阅过程分析了。

仲部分 信号和波##\

  刚才咱们说过,signal有几乎单子类,每一个型的signal订阅过程实际上大同小异,而且最初常见的也就是RACDynamicSignal,其实我们不需要极关注这题目,因为无论从定义信号,还是框架定义的有category,例如,textFiled的rac_textSignal属性,大多数且是RACDynamicSignal。另一个大面积的型RACSubject可以下理解。

  还有就是是,我们正好说到了三种植事件,分别是next、error、complete,和分析next的订阅过程同样,举个例证,我们发送网络要,希望当阴差阳错的时节,能被用户提示,那么首先,创建信号的时刻,在网络要失败的回调中,我们而[subscriber
sendError:netError],也就是殡葬错误事件。然后于订阅错误事件,也便是subscriberError:…这样便形成了左信号的订阅。

  complete事件比异常,它发生已订阅关系之象征,我们先行盖了解一下RACDispoable目标吧,我们解,订阅关系要出住的下,比如,在tableViewCell的复用的时段,cell会订阅model类有一个信号,但是当cell被复用的时节,如果未将之前的订阅关系取消掉,就会产出又订阅了2只model的情形。我们可窥见,subscribeNext、subscribeError、subscribeComplete事件返回的且是RACDisopable对象,当我们盼望歇订阅的上,调用[RACDisposable
dispose]就好了。complete也是这个原理。

老三局部 进一步的深刻##\

  RAC是一个良巨大之框架,平时之有课会误导大家纠结flattenMap和map的分别,这些题材,让人口摸不顶头绪,导致入门更加的不方便。实际上,学习她需一个循循渐进的历程,RAC有成百上千作用,解耦合,更高效之化解一近似问题等等,总之,他是本着正常的面向对象编程很好的填补。所以,在知道了订阅的历程后,重要的凡,投入其实的运用中,我观察了众多开源的品种,并结自己之履发现,其实flattenMap这样的操作,非常少,几乎没,常用之单就是是以下几单:手动构建信号(createSignal)、订阅信号(subscribeNext)、使用框架的有些宏定义(RACObserve、RAC)、然后就是学习几个最好简单易行的操作,例如map、merge等就是足以起了。如果期望深入研讨,一定要是管这些基础的事物吃透,然后在上学再多的操作,例如flattenMap,了解side
effect和多播的概念,学会RACSubject的用法(这个呢是特别重大的对象)等等。如果拿这些操作比作武器的话,可能再度要的凡内功,也即是了解他的思量,我们怎么样通过实战,知道当的采取他的强大,慢慢的熟悉与深入是回至渠道成的业务。