RAC的简单使用

新项目今天提测,项目中用到了RAC&MVVM框架,简单记录下RAC的简单使用

项目是OC开发,用的是ReactiveObjC库

RAC — ReactiveCocoa(RAC)  Github 上的一个开源函数响应编程框架!!

RAC里面最常见和常用的类

RACSignal  信号类

1.通过RACSignal创建一个信号 (默认是一个冷信号);

2.通过订阅者,订阅这个信号 (变成热信号);

3.发送信号

RACDisposable:它可以帮助我们取消订阅.

RACSubscriber(协议):订阅者(发送信号!)

RACSubject :信号提供者,自己可以充当信号,又能够发送信号!

RACReplaySubject: 可以先发送信号,再订阅,也可以先订阅再发送




RAC常用场景

可以代替代理

[[view rac_signalForSelector:@selector(btnclick:)] subscribeNext:^(RACTuple* _Nullablex) {

    }];

可以代替KVO

[[view rac_valuesForKeyPath:@"frame"observer:self] subscribeNext:^(id _Nullablex) {

 //x 是监听的属性改变的结果

 NSLog(@"%@",x);

    }];

监听事件

[[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindofUIControl* _Nullablex) {

 NSLog(@"点击了");

    }];

代替通知

[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {      

  NSLog(@"%@",x);    

}];

ps:虽然使用RAC代替通知可以免去手动移除通知的方法,但是又多了一步移除信号的操作.个人建议,用通知的话,还是用系统方法吧

监听文本框

[_tf.rac_textSignal subscribeNext:^(NSString * _Nullable x) {

        NSLog(@"%@",x);

    }];

用于监听 UITextField 和 UITextView 文本的改变,比写代理什么的,方便多了

定时器

self.disposable = [[RACSignal interval:1.f onScheduler:[RACScheduler scheduler]]subscribeNext:^(NSDate * _Nullable x) {

        //x是当前系统时间

        NSLog(@"%@",x);


        /* 关闭计时器 */

        [_disposable dispose];

    }];

ps:这个需要完成后关闭计时器

rac_liftSelector  适用于处理多个请求,都返回结果之后,刷新UI

RACSignal * signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {

        NSLog(@"1111");

        [subscriber sendNext:@"数据1"];

        return nil;

    }];

    RACSignal * signal2 = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {

        NSLog(@"2222");

        [subscriber sendNext:@"数据2"];

        return nil;

    }];

[self rac_liftSelector:@selector(setupData::) withSignalsFromArray:@[signal1,signal2]];

使用注意事项:

几个信号,selector的方法就几个参数,每个参数对应信号发出的数据。

不需要主动订阅,内部会主动订阅

RACMulticastConnection  信号连接类,适用于一个信号有多个订阅者

RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {

        [subscriber sendNext:@"请求到的数据"];

        returnnil;

    }];

    RACMulticastConnection* connection = [signal publish];

    [connection.signal subscribeNext:^(id  _Nullablex) {

        NSLog(@"订阅的信号%@-----1",x);

    }];

    [connection.signal subscribeNext:^(id  _Nullablex) {

        NSLog(@"订阅的信号%@-----2",x);

    }];

    [connection connect];

RACCommand 创建命令

RACCommand* command = [[RACCommandalloc]initWithSignalBlock:^RACSignal*_Nonnull(id  _Nullableinput) {

        //input:指令  就是下边execute: 传的参数

        return [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {

            [subscriber sendNext:@"发送的数据"];

            //发送完成  写上命令才会监听到执行完毕

            [subscribersend Completed];

            returnnil;

        }];

    }];

    //监听有没有执行完毕

    [command.executing subscribeNext:^(NSNumber*_Nullablex) {

        if([x boolValue]){//正在执行!!

            NSLog(@"正在执行!!");

        }else{

            NSLog(@"已经结束或还没开始做");

        }

    }];

[command.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {

        NSLog(@"订阅-----%@",x);//这里就是上边发送的数据

    }];



RAC常用的宏

给某个对象的某个属性绑定信号,一旦信号产生数据,就会将内容赋值给属性!

    RAC(_label,text) = _textF.rac_textSignal;

只要这个对象的某个属性发生变化  类似KVO

    [RACObserve(self.label,text)subscribeNext:^(id  _Nullablex) {

        NSLog(@"%@",x);

    }];

包装元祖

    RACTuple* tuple =RACTuplePack(@"1",@"2");

解包

    RACTupleUnpack(NSString * str) = tuple;

解决循环引用问题  需要配套使用

    @weakify(self);

    @strongify(self);



RAC过滤

filter 过滤条件  筛选不通过的值

[[_textField.rac_textSignal filter:^BOOL(NSString * _Nullable value) {

        //value:源信号的内容

        NSLog(@"value----%@",value);

        return [value length] >5;

        //返回值:就是过滤条件,只有满足这个条件,才能获取到内容

    }]subscribeNext:^(NSString*_Nullablex) {

        NSLog(@"x------%@",x);

    }];

ignore 忽略一些值!! 一次只能忽略一个对象

RACSubject * subject = [RACSubject subject];

  [[[subject ignore:@"ahaha"] ignore:@"1234"]subscribeNext:^(id  _Nullablex) {

        NSLog(@"%@",x);

    }];

take\takeLast  拿出前边几条数据或者后边几条数据

    RACSubject* subject = [RACSubject subject];

    [[subject takeLast:3]subscribeNext:^(id  _Nullablex) {

        NSLog(@"%@",x);

    }];

take:指定拿前面的哪几条数据!!(从前往后)  根据发送数据的前几条

takeLast: 取出发送的数据中 后面几条数据   ps: 必须调发送结束的方法后才会有数据返回

takeUntil  标记信号  取出数据 直到标记的信号发送数据截止

RACSubject * subject = [RACSubject subject];

    //标记信号

    RACSubject* tagSubject = [RACSubjectsubject];

    [[subjecttakeUntil:tagSubject]subscribeNext:^(id  _Nullablex) {

        NSLog(@"x------%@",x);

    }];

distinctUntilChanged 忽略掉重复数据

   RACSubject * subject = [RACSubject subject];

    [[subjectdistinctUntilChanged] subscribeNext:^(id  _Nullable x) {

        NSLog(@"%@",x);

    }];

skip  按照发送数据的顺序略过几个值

    RACSubject * subject = [RACSubject subject];

    [[subjectskip:2]subscribeNext:^(id  _Nullablex) {

        NSLog(@"%@",x);

    }];

RAC遍历字典或者数组

遍历数组

[arr.rac_sequence.signal subscribeNext:^(id  _Nullable x) {

        NSLog(@"%@",x);

    }];

遍历字典

[dic.rac_sequence.signal subscribeNext:^(id  _Nullable x) {

        //这里x是元组,每个元组中包含字典的一对键值对 x[0]为key  x[1]为value

        RACTupleUnpack(NSString * key,NSString * value) = x;

        NSLog(@"%@---%@",key,value);

    }];

组合信号

 concat  按顺序组合

    RACSubject* subject1 = [RACSubject subject];

    RACSubject* subject2 = [RACSubject subject];

    RACSubject* subject3 = [RACSubject subject];

    //订阅信号

    [[RACSignal concat:@[subject1,subject2,subject3]]subscribeNext:^(id  _Nullablex) {

        NSLog(@"%@",x);

    }];

ps: subject1 发送结束才会接受 subject2,依次类推

merge  组合信号  根据发送的情况接收数据,与数组中的顺序没有关系,哪个先发送就先收到哪个

    RACSubject* subject1 = [RACSubject subject];

    RACSubject* subject2 = [RACSubject subject];

    RACSubject* subject3 = [RACSubject subject];

    RACSignal* signal = [RACSignal merge:@[subject2,subject3,subject1]];

    [signalsubscribeNext:^(id  _Nullablex) {

        //任意一个信号发送内容就会来这个Block

        NSLog(@"%@",x);

    }];

zipWith : 两个信号压缩!只有当两个信号同时发出信号内容,并且将内容合并成为一个元组

    RACSubject* subject1 = [RACSubject subject];

    RACSubject* subject2 = [RACSubject subject];

    [[subject1 zipWith:subject2]subscribeNext:^(id  _Nullablex) {

        //只有两个信号都发送数据  才会来到这里  少一个不行

       //比如,subject1 发送了一个字符串@"1",又发送了一个字符串@"2",这时subject2才发送一个字符串@"a",那么这里过来的是@"2"和@"a"组成的元组

        NSLog(@"%@",x);

    }];



RAC个人感觉配合MVVM使用更方便些

比如,在 viewModel 中请求数据/处理数据, VC中订阅信号即可

viewModel 中

        @weakify(self);

        _parseCommand= [[RACCommand alloc] initWithSignalBlock:^RACSignal*_Nonnull(id  _Nullableinput) {

            return [RACSignal createSignal:^RACDisposable*_Nullable(id  _Nonnullsubscriber) {

                @strongify(self);

                [Network postRequestWithApi:api param:nil result:^(id data) {

                         [subscriber sendNext:self.dataArr];

                        [subscriber sendCompleted];

                }];

                return nil;

            }];

        }];

    }

VC中

@weakify(self);

    [self.viewModel.parseCommand.executionSignals.switchToLatest subscribeNext:^(id  _Nullable x) {

        @strongify(self);

    }];

    [self.viewModel.parseCommand execute:param];

或者

viewModel中

- (RACSignal*)signalForSearchOrgWithName:(NSString*)orgName

{

    @weakify(self);

    RACSignal * signal = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {

        @strongify(self);

      [subscriber sendNext:self.orgDataArr];  

      [subscriber sendCompleted];      

        return nil;

    }];

    return signal;

}

然后在VC中调用订阅



在tableview的cell使用,需要注意复用的问题

@weakify(self);

    [[[photoCell.photographBtn rac_signalForControlEvents:UIControlEventTouchUpInside] takeUntil:photoCell.rac_prepareForReuseSignal] subscribeNext:^(__kindof UIControl * _Nullable x) {

        @strongify(self);

    }];

你可能感兴趣的:(RAC的简单使用)