您的位置:首页 > Web前端 > React

iOS ReactiveCocoa 使用详解(二)

2017-07-25 16:29 435 查看
ReactiveCocoa 用法实例如下:

一、常见方法

  1、代替代理
   rac_signalForSelector:用于替代代理
    // 1.代替代理,RACSubject
    // RAC方法:可以判断下某个方法有没有调用
    //只要self调用Selector就会产生一个信号
    // rac_signalForSelector:监听某个对象调用某个方法
   
    [[self rac_signalForSelector:@selector(didReceiveMemoryWarning)]
subscribeNext:^(id x) {
        NSLog(@"控制器调用了didReceiveMemoryWarning");
    }];

    //判断下redView有没有调用btnClick,就表示点击了按钮
    [[_redView rac_signalForSelector:@selector(btnClick:)]
subscribeNext:^(id x) {
        NSLog(@"点击了按钮");

    }];

 
2、代替KVO

rac_valuesAndChangesForKeyPath:用于监听某个对象的属性改变

[_redView rac_observeKeyPath:@"name" options:NSKeyValueObservingOptionNew
observer:nil block:^(id value,
NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent)
{
        // 只要监听的属性一改变调用
        NSLog(@"%@",_redView.name);

}];

// KVO:第二种,只要对象的值改变,就会产生信号,订阅信号

     [[_redView rac_valuesForKeyPath:@"name" observer:nil]
subscribeNext:^(id x) {

     }];

 
3、监听事件

        rac_signalForControlEvents:用于监听某个事件

    //只要按钮产生这个事件,就会产生一个信号

    [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {

        

        NSLog(@"按钮被点击%@",x);

    }];

    _btn.rac_command = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {

        NSLog(@"按钮点击");

        return [RACSignal empty];

    }];

  4、代替通知

    rac_addObserverForName:用于监听某个通知

   [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x)
{

        

        NSLog(@"%@",x);

    }];

  5、监听文本框文字改变 

rac_textSignal:只要文本框发出改变就会发出这个信号

[_textField.rac_textSignal subscribeNext:^(id x) {

        // x:文本框的文字

        NSLog(@"%@",x);

}];

  6、处理当界面有多次请求时,需要都获取到数据时,才能展示界面

rac_liftSelector:withSignalsFromArray:Signals:当传入的Signals(信号数组),

每一个signal都至少sendNext过一次,就会去触发第一个selector参数的方法

RACSignal *requestHot = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber>
subscriber) {

      NSLog(@"请求最热商品");

      [subscriber sendNext:@"获取最热商品"];

      return nil;

}];

    

RACSignal *requestNew = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber>
subscriber) {

      NSLog(@"请求最新商品");

      //[subscriber sendNext:@"获取最新商品"];

      return nil;

}];

    

    //
Selector调用:当所有信号都发送数据的时候调用
    // 数组存放信号
    // Selector注意点:参数根据数组元素决定
    // Selector方法参数类型,就是信号传递出来数据
    [self rac_liftSelector:@selector(updateUI:data2:) withSignalsFromArray:@[requestHot,requestNew]];

二、常见宏

  1、RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于给某个对象的某个属性绑定

    // 给某个对象的某个属性绑定一个信号,只要产生信号,就会把信号的内容给对象的属性赋值

    // 给label的text属性绑定一个信号

    RAC(_label,text) = _texfField.rac_textSignal;

 
2、RACObserve(self, name):监听某个对象的某个属性,返回的是信号

    // 观察某个对象某个属性

    [RACObserve(self, name) subscribeNext:^(id x)
{

        

        NSLog(@"%@",x);

    }];

 3、 @weakify(Obj)和@strongify(Obj),一般两个都是配套使用,解决循环引用问题

  4、RACTuplePack:把数据包装成RACTuple(元组类)

    // RACTuplePack:快速把一些数据包装成元组类

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

 
5、RACTupleUnpack:把RACTuple(元组类)解包成对应的数据

    // 参数:需要解析生成出来变量名

    RACTupleUnpack(NSString *str,NSNumber *num) = tuple;

    NSLog(@"%@ %@",str,num);

三、常见操作方法

1、ReactiveCocoa操作原理

  所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中,

  因此只要继承RACStream就有了操作处理方法 

2、ReactiveCocoa操作思想

  运用的是Hook(钩子)思想,Hook是一种用于改变API(应用程序编程接口:方法)执行结果的技术. 

  Hook用处:截获API调用的技术。 Hook原理:在每次调用一个API返回结果之前,先执行你自己的

  方法,改变结果的输出

3、ReactiveCocoa核心方法bind

  ReactiveCocoa操作的核心方法是bind(绑定),而且RAC中核心开发方式,也是绑定,之前的

  开发方式是赋值,而用RAC开发,应该把重心放在绑定,也就是可以在创建一个对象的时候,就绑定

  好以后想要做的事情,而不是等赋值之后在去做事情

核心方法bind的使用:

     RACSignal *bindSignal = [_textField.rac_textSignal bind:^RACStreamBindBlock{

     // block调用时刻:只要一个信号被绑定就会调用.表示信号绑定完成

     NSLog(@"源信号被绑定");

     return ^RACStream *(id value, BOOLBOOL *stop){

            // RACStreamBindBlock什么时候调用:每次源信号发出内容,就会调用这个block

            

            // value:源信号发出的内容

            NSLog(@"源信号发出的内容:%@",value);

            

            // RACStreamBindBlock作用:在这个block处理源信号的内容

            value = [NSString stringWithFormat:@"xmg%@",value];

            // block返回值:信号(把处理完的值包装成一个信号,返回出去)

            

           
// 创建一个信号,并且这个信号的传递的值是我们处理完的值,value

            return [RACReturnSignal
return:value];

        };

    }];

    

   
// 订阅绑定信号,不在是源信号

    [bindSignal subscribeNext:^(id x) {

        

        NSLog(@"%@",x);

    }];

    // 执行流程

    /*

     1.文字改变源信号

     2.绑定源信号,[_textField.rac_textSignal bind]

     * 调用bind返回绑定好的信号,didSubscribe

     3.订阅绑定信号

     * 创建订阅者

     * 调用绑定信号的didSubscribe

     4.执行绑定信号didSubscribe

     5.执行bind方法传入的block

     6.订阅源信号

     7.只要源信号一发出内容,就会调用id signal = bindingBlock(x, &stop);

     * signal:把值处理完的信号 

    */

 
    ReactiveCocoa操作方法之映射(flattenMap,Map)

 
 flattenMap:信号中信号,signalOfSignals

    [[_textField.rac_textSignal flattenMap:^RACStream *(id value) {

        // value:源信号的内容

        value = [NSString stringWithFormat:@"xmg%@",value];

        // 返回值:信号,把处理完的值包装成信号返回出去

        return [RACReturnSignal return:value];

    }] subscribeNext:^(id x) {

        // 订阅[RACReturnSignal return:value发送值

        

        // x:绑定信号的值

        NSLog(@"%@",x);

    }];

 
 map: 用于普通信号,信号发出普通值

    [[_textField.rac_textSignal map:^id(id value) {

        // value:源信号的内容

        // 返回值,就是处理源信号的内容,直接返回

        return [NSString stringWithFormat:@"----xmg%@",value];

        

    }] subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

FlatternMap和Map的区别

1.FlatternMap中的Block返回信号。

2.Map中的Block返回对象。

3.开发中,如果信号发出的值不是信号,映射一般使用Map

4.开发中,如果信号发出的值是信号,映射一般使用FlatternMap。

四、操作方法之组合

 
 1、concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号

   // concat:连接信号,有顺序的拼接,一定要等第一个信号完成的时候,第二个信号才会被激活

    RACSubject *signalA = [RACSubject
subject];

    RACSubject *signalB = [RACSubject
subject];

    

    // 组合信号

    RACSignal *signals = [signalA
concat:signalB];

    

    // 订阅组合信号

    [signals subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

    // 发送数据

    [signalA sendNext:@1];

    [signalA sendCompleted];

    [signalB sendNext:@2];

 
 2、then:用于连接两个信号,当第一个信号完成,才会连接then返回的信号

    RACSubject *signalA = [RACSubject
subject];

    RACSubject *signalB = [RACSubject
subject];

    

    // 组合

    RACSignal *signals = [signalA
then:^RACSignal *{

        return signalB;

    }];

    

    [signals subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

    [signalA sendNext:@1];

    [signalA sendCompleted];

    [signalB sendNext:@2];

then跟concat区别:监听不到第一个信号的值,共同点:都是必须第一个信号完成,第二个信号才会激活

 
 3、merge: 把多个信号合并为一个信号,任何一个信号有新值的时候就会调用

// merge:合并,任何一个信号只要发送值,就能订阅

    RACSubject *signalA = [RACSubject
subject];

    RACSubject *signalB = [RACSubject
subject];

    

    RACSignal *signals = [signalA
merge:signalB];

    

    [signals
subscribeNext:^(id x) {

        NSLog(@"%@",x);

    }];

    

    [signalA
sendNext:@1];

    

   
[signalB sendNext:@2];

    

    [signalB
sendNext:@3];

 
 4、zipWith:把两个信号压缩成一个信号,只有当两个信号同时发出信号内容时,

 
  并且把两个信号的内容合并成一个元组,才会触发压缩流的next事件

    RACSubject *signalA = [RACSubject subject];

    RACSubject *signalB = [RACSubject subject];

    

    RACSignal *signals = [signalA zipWith:signalB];

    

    [signals subscribeNext:^(id x) {

        

        NSLog(@"%@",x);

    }];

    

    // zipWith:当两个信号都发出内容的时候,才能被订阅到

    [signalA sendNext:@1];

    [signalB sendNext:@2];

    

    [signalB sendNext:@3];

    [signalA sendNext:@4];

 
 5、combineLatest:将多个信号合并起来,并且拿到各个信号的最新的值,必须每个合并的signal至少都

 
  有过一次sendNext,才会触发合并的信号

    // 第一个参数:就是存放需要合并信号

    [[RACSignal combineLatest:@[_textField1.rac_textSignal,_textField2.rac_textSignal] reduce:^id(NSString
*str1,NSString *str2){

        NSLog(@"%@ ---- %@",str1,str2);

        // block:只要任意一个信号发出内容,就会调用

        // block参数个数:由信号决定

        // block参数类型:block的参数就是信号发出值

        // 把两个信号中的值聚合成哪个值

        return @(str1.length && str2.length);

    }] subscribeNext:^(id x) {

        _btn.enabled = [x boolValue];

        NSLog(@"%@",x);

    }];

6、reduce聚合:用于信号发出的内容是元组,把信号发出元组的值聚合成一个值

    RACSignal *signalA = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber>
subscriber) {

        [subscriber sendNext:@1];

        return nil;

    }];

    

    RACSignal *signalB = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber>
subscriber) {

        [subscriber sendNext:@2];

        return nil;

    }];

    

    // 聚合

    // 常见的用法,(先组合在聚合)。combineLatest:(id<NSFastEnumeration>)signals reduce:(id (^)())reduceBlock

    // reduce中的block简介:

    // reduceblcok中的参数,有多少信号组合,reduceblcok就有多少参数,每个参数就是之前信号发出的内容

    // reduceblcok的返回值:聚合信号之后的内容。

    RACSignal *reduceSignal = [RACSignal combineLatest:@[signalA,signalB] reduce:^id(NSNumber
*num1 ,NSNumber *num2){

        return [NSString stringWithFormat:@"%@ %@",num1,num2];

    ];  

        

    [reduceSignal subscribeNext:^(id x) {  

            NSLog(@"%@",x);  

    }];

五、操作方法之过滤

filter:过滤信号,使用它可以获取满足条件的信号
ignore:忽略完某些值的信号
distinctUntilChanged:当上一次的值和当前的值有明显的变化就会发出信号,否则会被忽略掉
take:从开始一共取N次的信号
takeLast:取最后N次的信号,前提条件,订阅者必须调用完成,因为只有完成,就知道总共有多少信号
takeUntil:(RACSignal *):获取信号直到执行完这个信号
skip:(NSUInteger):跳过几个信号,不接受
switchToLatest:用于signalOfSignals(信号的信号),有时候信号也会发出信号,会在signalOfSignals中,获取signalOfSignals发送的最新信号

六、操作方法之秩序
doNext: 执行Next之前,会先执行这个Block
doCompleted: 执行sendCompleted之前,会先执行这个Block

七、操作方法之线程
deliverOn: 内容传递切换到制定线程中,副作用在原来线程中,把在创建信号时block中的代码称之为副作用
subscribeOn: 内容传递和副作用都会切换到制定线程中

八、操作方法之时间

timeout:超时,可以让一个信号在一定的时间后,自动报错
interval 定时:每隔一段时间发出信号
delay: 延迟发送next

九、操作方法之重复

retry重试 :只要失败,就会重新执行创建信号中的block,直到成功
replay重放:当一个信号被多次订阅,反复播放内容
throttle节流:当某个信号发送比较频繁时,可以使用节流,在某一段时间不发送信号内容,过了一段时间获取信号的最新内容发出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ReactiveCocoa