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

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

  六 、看起来下面两段代码有提到,可是实际怎么效率的?

先是某个 订阅者和信号##\

  ① 、隐藏的订阅者

  平常大家打交道的就是信号,可是接连说订阅,却不知晓订阅到底是怎么着举办的,也无力回天解答上边的标题,让大家依据源码分析一下订阅进度。

  首先来认识二个对象:订阅者(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类型的品质,此处,大家可以答应上边第四个难题,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的调用。到那边,大家着力把信号和订阅者,以及订阅进程分析落成。

初学者总是简单被一堆概念搞得晕头转向,小编想实在只是是那三种:

在RAC里面,大家富有围绕的事物无非主体是这几样:信号(signal)、订阅者(subscriber)、还有关于信号的生产者实体、信号的买主,那多少个的关系。
咱俩怎么采用RAC,因为它解耦太好了,除此之外,它简洁,合营MVVM能发布出很大的效果等等。相信大家都写腻了对象时期的纷纭通讯、一大堆状态的制造和治本、越来越难有限援救的业务逻辑,那些就是RAC诞生的沉重。

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

  ④ 、subscribeNext又是怎么样?五 、那几个block哪一天调用?

让大家先来缓解位置的迷离吧!

其次部分 信号和事件##\

  刚才大家说过,signal有多少个子类,每1个品类的signal订阅进程实际上泰安小异,而且最初常见的相当于RACDynamicSignal,其实大家不须要太关切那个题材,因为随便自定义信号,照旧框架定义的一对category,例如,textFiled的rac_textSignal属性,半数以上都以RACDynamicSignal。另三个大面积的类型RACSubject可以以往领悟。

  还有就是,大家恰好谈到了三种事件,分别是next、error、complete,和分析next的订阅进度一样,举个例证,我们发送互联网请求,希望在失误的时候,能给用户提示,那么首先,制造信号的时候,在互连网请求战败的回调中,大家要[subscriber
sendError:netError],相当于殡葬错误事件。然后在订阅错误事件,也等于subscriberError:…那样就成功了错误信号的订阅。

  complete事件比较卓殊,它有终止订阅关系的代表,大家先大概领悟一下RACDispoable对象呢,大家驾驭,订阅关系须要有终止的时候,比如,在tableViewCell的复用的时候,cell会订阅model类爆发贰个信号,不过当cell被复用的时候,若是不把前面的订阅关系撤消掉,就会出现同时订阅了二个model的景况。大家得以窥见,subscribeNext、subscribeError、subscribeComplete事件重临的都以RACDisopable对象,当大家盼望截至订阅的时候,调用[RACDisposable
dispose]就可以了。complete也是以此规律。

  一 、createSignal好难啊;贰 、subscriber是什么样?三 、那个block几时调用?

大家在领略到RAC的精锐和神乎其神的时候,要求思想五个地点:一 、它是什么兑现的?第①个难点则更有难度:② 、它是如何想到那样设计的?
那边大家先品尝探讨第3个难题,它是怎样贯彻的,分析重点的系统。

其三部分 进一步的中肯##\

  RAC是三个特出巨大的框架,平时的有个别科目会误导我们纠结flattenMap和map的分化,这么些问题,让人找不到头绪,导致入门尤其的困顿。实际上,学习它须求二个循循渐进的经过,RAC有那多少个效益,解耦合,更便捷的缓解一类题材等等,同理可得,他是对不奇怪的面向对象编程很好的填补。所以,在知晓完订阅的进度之后,紧要的是,投入实际的应用中,作者观看了不少开源的系列,并组成本人的举办发现,其实flattenMap那样的操作,卓殊少,大概没有,常用的仅仅就是以下多少个:手动创设信号(createSignal)、订阅信号(subscribeNext)、使用框架的一对宏定义(RACObserve、RAC)、然后就是学习多少个最不难易行的操作,例如map、merge等就可以初阶了。要是希望浓密商讨,一定要把这一个基础的事物吃透,然后在念书越多的操作,例如flattenMap,了然side
effect和多播的定义,学会RACSubject的用法(那一个也是可怜主要的对象)等等。倘使把这几个操作比作武器的话,或者更要紧的是内功,约等于清楚他的思辨,大家怎么着通过实战,知道确切的应用他的兵不血刃,逐渐的耳熟能详和深入是马到功成的业务。