ios专题iOS开发

ReactiveCocoa(简称RAC)基础篇

2018-04-24  本文已影响8人  HeavenWong

参考文章1袁峥
参考文章2
参考文章3
参考文章4

一、ReactiveCocoa简介

二、好用编程思想

//  第三方库masnory简单使用
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.mas_equalTo(0);
        make.centerY.mas_equalTo(-150);
        make.width.mas_equalTo(88);
        make.height.mas_equalTo(50);
    }];

2.1 实学实用

manager.add(2,2).sub(1).muilt(2).divide(3);

1. 在OC中,block可以用`方法名()`的方式来调用,调用Block的时候,blockName(params)。所以add(param)和sub(param)这两个方法,肯定返回值是一个Block,而且是带一个参数的Block。
2. 通过 `.` 调用方法其实就是调用getter方法,所以add和sub方法没有参数,只有一个返回类型为Block的值。
3. 为什么能一直点下去,因为Block也有返回值,而且返回值的类型就是当前对象的类型。
2.2 使用链式编程+函数编程来写一个计算器功能
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class WMCalculateManager;

typedef WMCalculateManager *(^CalculateName)(CGFloat value);// 声明一个公开类型:带CGFloat类型的参数,返回WMCalculateManager类型,名字为CalculateName的block类型

@interface WMCalculateManager : NSObject

@property (nonatomic, copy) CalculateName calculateName;

// 参数(函数):带有本类对象的、无返回值类型 函数(block)
+ (CGFloat)makeCalculateManagerWith:(void(^)(WMCalculateManager *manager))managerBlock;

- (WMCalculateManager *(^)(CGFloat value1,CGFloat value2))add;
- (CalculateName)sub;
- (CalculateName)muilt;
- (CalculateName)divide;

@end
@interface WMCalculateManager ()

@property (nonatomic, assign) CGFloat result;

@end

@implementation WMCalculateManager
+ (CGFloat)makeCalculateManagerWith:(void (^)(WMCalculateManager *))managerBlock {
    // 创建自身实例化
    WMCalculateManager *manager = [[WMCalculateManager alloc] init];
    // 调用managerBlock,把 自身实例化对象 当参数
    managerBlock(manager);
    // 返回值
    return manager.result;;
}

- (WMCalculateManager *(^)(CGFloat value1, CGFloat value2))add {
    // 返回值 是 一个 带 自身返回值 和 参数 的函数
    return ^WMCalculateManager *(CGFloat value1, CGFloat value2){
        _result = value1 + value2 ;
        return self;
    };
}

- (CalculateName)sub {
    return ^WMCalculateManager *(CGFloat value1) {
        _result -= value1;
        return self;
    };
}

- (CalculateName)muilt {
    return ^WMCalculateManager *(CGFloat value1) {
        _result = _result * value1;
        return self;
    };
}

- (CalculateName)divide {
    return ^WMCalculateManager *(CGFloat valuea) {
        _result = _result / valuea;
        return self;
    };
}

@end
CGFloat result = [WMCalculateManager makeCalculateManagerWith:^(WMCalculateManager *manager) {
        manager.add(2,2).sub(1).muilt(2).divide(3);
    }];
    _resultLab.text = [NSString stringWithFormat:@"结果:%.1f",result];
    NSLog(@"result:%.1f",result);
// 输出结果:result:2.000000


三、ReactiveCocoa编程思想

四、ReactiveCocoa使用

4.1. ReactiveCocoa导入

pod 'ReactiveObjC'

4.2 ReactiveCocoa常用的应用场景

// 1.代替代理
    // 需求:自定义redView,监听红色view中按钮点击
    // 之前都是需要通过代理监听,给红色View添加一个代理属性,点击按钮的时候,通知代理做事情
    // rac_signalForSelector:把调用某个对象的方法的信息转换成信号,就要调用这个方法,就会发送信号。
    // 这里表示只要redV调用btnClick:,就会发出信号,订阅就好了。
    [[redV rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(id x) {
        NSLog(@"点击红色按钮");
    }];

    // 2.KVO
    // 把监听redV的center属性改变转换成信号,只要值改变就会发送信号
    // observer:可以传入nil
    [[redV rac_valuesAndChangesForKeyPath:@"center" options:NSKeyValueObservingOptionNew observer:nil] subscribeNext:^(id x) {
        NSLog(@"%@",x);
    }];

    // 3.监听事件
    // 把按钮点击事件转换为信号,点击按钮,就会发送信号
    [ __weak typeof(self) weakSelf = self;// 注意:block中self要弱引用,避免强强引用无法释放。
    [[btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        // 点击按钮就会来到这里发送信号
        [weakSelf caculateName1:btn];
    }];

    // 4.代替通知
    // 把监听到的通知转换信号
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(id x) {
        NSLog(@"键盘弹出");
    }];

    // 5.监听文本框的文字改变
   [_textField.rac_textSignal subscribeNext:^(id x) {
       NSLog(@"文字改变了%@",x);
   }];
   
   // 6.处理多个请求,都返回结果的时候,统一做处理.
    RACSignal *request1 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 发送请求1
        [subscriber sendNext:@"发送请求1"];
        return nil;
    }];
    
    RACSignal *request2 = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        // 发送请求2
        [subscriber sendNext:@"发送请求2"];
        return nil;
    }];
    
    // 使用注意:几个信号,参数一的方法就几个参数,每个参数对应信号发出的数据。
    [self rac_liftSelector:@selector(updateUIWithR1:r2:) withSignalsFromArray:@[request1,request2]];  
    
}
// 更新UI
- (void)updateUIWithR1:(id)data r2:(id)data1
{
    NSLog(@"更新UI%@  %@",data,data1);
}

4.3. ReactiveCocoa常用方法

RACSignal 信号类
// RACSignal使用步骤:
    // 1.创建信号 + (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe
    // 2.订阅信号,才会激活信号. - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
    // 3.发送信号 - (void)sendNext:(id)value
    
    
    // RACSignal底层实现:
    // 1.创建信号,首先把didSubscribe保存到信号中,还不会触发。
    // 2.当信号被订阅,也就是调用signal的subscribeNext:nextBlock
    // 2.2 subscribeNext内部会创建订阅者subscriber,并且把nextBlock保存到subscriber中。
    // 2.1 subscribeNext内部会调用siganl的didSubscribe
    // 3.siganl的didSubscribe中调用[subscriber sendNext:@1];
    // 3.1 sendNext底层其实就是执行subscriber的nextBlock
    
    // 1.创建信号 先保存信号代码,还不会被触发
     _signal1 = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        // block调用时刻:每当有订阅者信号,就会调用block
        // 2. 发送信号
        [subscriber sendNext:@1];
        // 3.发送完成(如果不再发送数据,最好发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号)
        [subscriber sendCompleted];
        return [RACDisposable disposableWithBlock:^{
            // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
            
            // 执行完Block后,当前信号就不在被订阅了。
            DLog(@"发送完成或发送错误,总之信号被销毁");
        }];
    }];

 // 3.订阅信号,才会激活信号.
 [_signal1 subscribeNext:^(id  _Nullable x) {
        DLog(@"\n接收到数据:%@\n",x);
    }];

RACDisposable
RACSubject

4.4. ReactiveCocoa常见的宏

上一篇下一篇

猜你喜欢

热点阅读