RAC基础

作者: 夜沐月 | 来源:发表于2020-08-05 20:37 被阅读0次

RAC是一套基于Cocoa的FRP框架,它的优点是用户的输入转化为随时间改变的函数,取消了可变状态.在RAC的世界里,"万物"皆为信号,一个基础的信号创建,订阅,发送,销毁过程简单的可以用一下代码表示

 // 创建信号时传递参数block:由 返回值RACDisposable   参数subscriber  代码块组成

   @weakify(self);
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *  _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
  @strongify(self);
        // block代码块 会在信号订阅方法subscribeNext调用的时候执行
        [subscriber sendNext:@"RAC"];
        // 如果不再发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
          [subscriber sendCompleted];
        NSLog(@"subscriber == %@",subscriber);
        RACDisposable *disposable = [RACDisposable disposableWithBlock:^{
            // 销毁信号
            // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
            // 执行完Block后,当前信号就不在被订阅了。
            NSLog(@"开始销毁");
        }];
        return disposable;
        
    }];
    // 订阅信号,才会激活信号.
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"x == %@",x);
    }];

RAC的奇妙之处在于使用Block作为参数,Block可以封装了函数调用以及函数调用环境,然后在需要的地方调用.
当我们调用createSignal创建信号时,方法执行调用

RACDynamicSignal : 使用块实现其订阅行为的私有“RACSignal”子类
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    RACDynamicSignal *signal = [[self alloc] init];
    signal->_didSubscribe = [didSubscribe copy];
    return [signal setNameWithFormat:@"+createSignal:"];
}

此时产生信号,并用信号保存每个订阅者要调用的块.
创建信号后,调用订阅信号subscribeNext会执行

RACSubscriber
+ (instancetype)subscriberWithNext:(void (^)(id x))next error:(void (^)(NSError *error))error completed:(void (^)(void))completed {
    RACSubscriber *subscriber = [[self alloc] init];

    subscriber->_next = [next copy];
    subscriber->_error = [error copy];
    subscriber->_completed = [completed copy];

    return subscriber;
}

创建订阅者,并用属性保存订阅者Block,之后调用[self subscribe:o]

self是创建信号时的RACDynamicSignal所以调用[self subscribe:o]执行以下 这里类似类簇的应用
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
    NSCParameterAssert(subscriber != nil);

    RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
//subscriber用属性保存subscriber,用于在[subscriber sendNext:@"RAC"]执行时,调用[self.innerSubscriber sendNext:value]
    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;
}

此时创建销毁者RACCompoundDisposable, RACPassthroughSubscriber当不被销毁时将所有事件传递给另一个订阅者的私有订阅者.如果每个订阅者要调用的块didSubscribe存在,创建RACScheduler(调度者用于控制何时何地执行工作)的子类RACSubscriptionScheduler(仅用于订阅的私有调度者),默认主线程执行block,调用self.didSubscribe(subscriber)

- (RACDisposable *)schedule:(void (^)(void))block {
    NSCParameterAssert(block != NULL);

    if (RACScheduler.currentScheduler == nil) return [self.backgroundScheduler schedule:block];

    block();
    return nil;
}

接着将返回didSubscribe初始化的地方createSignal:
当调用 [subscriber sendNext:@"RAC"];时会执行

subscriber 为前面RACPassthroughSubscriber  也是应用类簇
- (void)sendNext:(id)value {
    if (self.disposable.disposed) return;

    if (RACSIGNAL_NEXT_ENABLED()) {
        RACSIGNAL_NEXT(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString([value description]));
    }
  
    [self.innerSubscriber sendNext:value];
}

此时[self.innerSubscriber sendNext:value];便触发订阅者的block调用

  [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"x == %@",x);
    }];

这样一个简单的信号创建,订阅,发送,销毁过程就结束了,整个过程应用类簇和block实现FRP
除了上述模式创建信号你也可以这样

RACReturnSignal
// 一个私有的“RACSignal”子类,它同步向任何订阅者发送信号,然后完成
 [[RACSignal return:@"123456"] subscribeNext:^(id  _Nullable x) {
        NSLog(@"-----%@",x);
    }];

RACErrorSignal
一个私有的“RACSignal”子类,它同步向任何订阅者
 RACSignal *signal = [RACSignal error:[NSError errorWithDomain:@"" code:404 userInfo:nil]];
    [signal subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@",x);
    }];

不同的信号用不同的子类创建,同时存储不同的属性

冷热信号

热信号 : 是主动的,即时没有订阅,它也会源源不断的推送,它可以有多个订阅者是一对多,集合与订阅者共享信息.
冷信号: 是被动的,每个订阅都是独立行为.每一订阅都会执行一次.

相关文章

  • RAC 详细解析

    RAC详细解析(一)—— 框架概览RAC详细解析(二)—— 基础使用方法

  • RAC基础

    获得信号的方式 1.Cocoa桥接 2.信号变换 3.序列转换RACSignal * sig4 = [RACSeq...

  • RAC基础

    RAC(ReactiveCocoa) 简单的说,RAC就是一个第三方库,他可以大大简化你的代码过程。 官方的说,R...

  • RAC 基础

    1.signal 2.RACSubject 3.RACTuple 元组类似一个数据的包装 ,类似是Dic的封装;S...

  • RAC基础

    RAC是一套基于Cocoa的FRP框架,它的优点是用户的输入转化为随时间改变的函数,取消了可变状态.在RAC的世界...

  • RAC基础

    最近接触学习到了RAC(ReactiveCocoa),RAC是函数式+响应式编程结合 我们在iOS开发中,页面之间...

  • 收录 : iOS - ReactiveCocoa(RAC)

    美团RAC技术文档 ReactiveCocoa基础ReactiveCocoa进阶 ReactiveCocoa教程:...

  • ReactiveObjC(RAC)基础

    最近学习了一下RAC的使用,参考了下面两篇文章 Jonzzs的【iOS 开发】ReactiveObjC(RAC)的...

  • iOS RAC学习

    一、RAC使用基础认知 RAC编程思想:响应式编程+函数式编程 在iOS中,类之间的传值,无非就是block、de...

  • 菜鸟用RAC基于AFNetworking 3.0网络的封装搭建记

    前言 这几天自己在学习RAC,学习了几天对RAC有了一定基础了解,如之前写的菜鸟开始学习ReactiveObjc运...

网友评论

    本文标题:RAC基础

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