ReactiveCocoa(RAC)的基本使用

响应式:通知,代理,KVO
RAC是函数响应式,优点:所有业务逻辑代码在一起便于阅读

用Cocopods导入
pod 'ReactiveObjC','~>3.0.0'

导入头文件
#import 
简单的例子
- (void)viewDidLoad {
    [super viewDidLoad];
    
    //创建信号
    RACSubject *subject = [RACSubject subject];
    //订阅信号:函数式编程思想
    //创建订阅者,将Block保存到订阅者对象中,将订阅者保存到数组中
    [subject subscribeNext:^(id  _Nullable x) {
        //回调
        NSLog(@"%@",x);
    }];
    //发送信号
    [subject sendNext:@"厉害了"];
}

1:代理 VS RAC

代理的流程:
代理:
1、定义协议
2、协议的方法
3、代理属性
4、代理属性有没有值!有没有响应我的协议方法!
外界:
1、设置代理
2、遵守协议
3、实现方法

案例:控制器页面上放一个View,View上面一个按钮,点击按钮,在控制器上接收信息

//RAC做法
//view.h中

#import 
@interface CusView : UIView

@property (nonatomic,strong) RACSubject *btnClickSubject; //信号

@end

//view.m中

//懒加载
- (RACSubject *)btnClickSubject{
    if (!_btnClickSubject) {
        _btnClickSubject = [RACSubject subject];
    }
    return _btnClickSubject;
}

//点击事件
- (IBAction)btnClick:(id)sender{
    [self.btnClickSubject sendNext:@""];
}

//Controller中
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CusView *cusView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.cusView.btnClickSubject subscribeNext:^(id  _Nullable x) {
        NSLog(@"收到了:%@",x);
    }];
}
@end
//下面是简化版:
自定义View中都不用写,直接在controller中监控View中的方法
//Controller中
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CusView *cusView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //监听View中的方法
    [[self.view rac_signalForSelector:@selector(btnClick:)] subscribeNext:^(RACTuple * _Nullable x) {
        NSLog(@"收到信号了!!!");
    }];
}
@end



//**************如果传值****************
//view.h中

#import 
@interface CusView : UIView
@end

//view.m中

//点击事件
- (IBAction)btnClick:(id)sender{
      [self send:@"嘿嘿"];
}

- (void)send:(id)objc{

}

//Controller中
@interface ViewController ()
@property (weak, nonatomic) IBOutlet CusView *cusView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //只要调用了send:方法就可以得到响应
    [[self.view rac_signalForSelector:@selector(send:)] subscribeNext:^(RACTuple * _Nullable x) {
        NSLog(@"收到信号了!!!%@",x);
    }];
}

2:KVO VS RAC

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.cusView addObserver:self forKeyPath:@"frame" options:(NSKeyValueObservingOptionNew) context:nil];

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    
}

- (void)dealloc{
    [self.cusView removeObserver:self forKeyPath:@"frame"];
}
//RAC做法
//头文件  
#import 

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.cusView rac_observeKeyPath:@"frame" options:(NSKeyValueObservingOptionNew) observer:nil block:^(id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
        //回调
    }];
}
//下面是简化版:
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[self.cusView rac_valuesForKeyPath:@"frame" observer:self] subscribeNext:^(id  _Nullable x) {
        
    }];
}

3:Target VS RAC

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [_btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
}

- (void)btnClick:(UIButton *)sender{
    
}
//RAC做法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof UIControl * _Nullable x) {
        //做一些操作
        NSLog(@"%@",x);
    }];
}

4:通知 VS RAC

- (void)viewDidLoad {
    [super viewDidLoad];
    //发送通知
   [[NSNotificationCenter defaultCenter] postNotificationName: UIKeyboardWillShowNotification object:nil];
    //(其他地方)接收通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(click:) name: UIKeyboardWillShowNotification object:nil];
}

- (void)click:(NSNotification *)noti{
    
}
//RAC做法
- (void)viewDidLoad {
    [super viewDidLoad];
    
   [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object:nil] subscribeNext:^(NSNotification * _Nullable x) {
        NSLog(@"%@",x);
    }];
}

5:监听textField VS RAC

使用代理UITextFieldDelegate
//RAC做法
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.textField.rac_textSignal subscribeNext:^(NSString * _Nullable x) {
        NSLog(@"%@",x);//实时的监听textField的输入
    }];
}

6:Timer VS RAC

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
        
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] run];//死循环
    }];
    
    [thread start];
    
}

- (void)timerMethod{
    NSLog(@"%@",[NSThread currentThread]);
}
//RAC做法
- (void)viewDidLoad {
    //基于GCD,效率高
    //[RACScheduler scheduler]在子线程
    //[RACScheduler mainThreadScheduler]在主线程
   [[RACSignal interval:1.0 onScheduler:[RACScheduler scheduler]] subscribeNext:^(NSDate * _Nullable x) {
        NSLog(@"%@----%@",x,[NSThread currentThread]);
    }];
}
ReactiveCocoa(RAC)的基本使用_第1张图片
计时器打印结果.png

小例子:按钮倒计时⏳


@interface ViewController ()
@property (nonatomic,strong) UIButton *btn;
@property (nonatomic,assign) int time;
@property (nonatomic,strong) RACDisposable *disposable;
@end

@implementation ViewController

- (void)sendClick:(id)sender{
    //改变状态
    self.btn.enabled = NO;
    //设置倒计时
    self.time = 10;
    //每一秒
    _disposable = [[RACSignal interval:1.0 onScheduler:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSDate * _Nullable x) {
        NSLog(@"%@",[NSThread currentThread]);
        //设置按钮文字
        NSString *btnText = self.time > 0 ? [NSString stringWithFormat:@"请骚等%d秒",self.time] : @"重新发送";
        [self.btn setTitle:btnText forState:self.time > 0 ? UIControlStateDisabled : UIControlStateNormal];
        if (self.time > 0) {
            self.btn.enabled = NO;
        }else{
            self.btn.enabled = YES;
            [_disposable dispose];//取消订阅
        }
        //减去时间
        self.time --;
    }];
}
@end

//用于给某个对象的某个属性绑定。(textF的文本付给label的text属性)
RAC(_label,text) = _textF.rac_textSignal;
//    [self.textField.rac_textSignal subscribeNext:^(id x) {  
//        self.label.text = x;  
//    }];

//观察self.view的frame,当frame变化的时候会响应
[RACObserve(self.view, frame) subscribeNext:^(id  _Nullable x) {
        
}];

//RACTuplePack:把数据包装成RACTuple(元组类)
// 把参数中的数据包装成元组
    RACTuple *tuple = RACTuplePack(@10,@20);

//RACTupleUnpack:把RACTuple(元组类)解包成对应的数据。
// 把参数中的数据包装成元组
    RACTuple *tuple = RACTuplePack(@"xmg",@20);

// 解包元组,会把元组的值,按顺序给参数里面的变量赋值
// name = @"xmg" age = @20
    RACTupleUnpack(NSString *name,NSNumber *age) = tuple;

关于循环引用

    @weakify(self);
    RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id  _Nonnull subscriber) {
        @strongify(self);
        NSLog(@"%@",self);
        return nil;
    }];

你可能感兴趣的:(ReactiveCocoa(RAC)的基本使用)