reactiveCocoa实践一

RACSignal
RACSignal: 有数据产生的时候 , 就使用 RACSignal
    
RACSignal 使用步骤 : 1. 创建信号   2. 订阅信号 3. 发送信号
   
    RACDisposable *(^didSubscribe)(
id <RACSubscriber> subscriber) = ^RACDisposable *( id <RACSubscriber> subscriber) {
       
// didSubscribe 调用 : 只要一个信号被订阅就会调用
       
// didSubscribe 作用 : 发送数据
        NSLog(
@" 信号被订阅 " );
       
// 3. 发送数据
        [subscriber sendNext:
@1 ];
       
       
return nil ;
    };
   
   
// 1. 创建信号 ( 冷信号 )
    RACSignal *signal = [RACSignal createSignal:didSubscribe];
   
   
// 2. 订阅信号 ( 热信号 )
    [signal subscribeNext:^(
id x) {
       
       
// nextBlock 调用 : 只要订阅者发送数据就会调用
       
// nextBlock 作用 : 处理数据 , 展示到 UI 上面
       
       
// x: 信号发送的内容
        NSLog(
@"%@" ,x);
    }];
   
   
// 只要订阅者调用 sendNext, 就会执行 nextBlock
   
// 只要订阅 RACDynamicSignal, 就会执行 didSubscribe
    // 前提条件是 RACDynamicSignal, 不同类型信号






RACDisposable
@interface ViewController ()

@property ( nonatomic , strong ) id <RACSubscriber> subscriber;

@end

@implementation ViewController

- (
void )viewDidLoad {
    [
super viewDidLoad ];
   
// Do any additional setup after loading the view, typically from a nib.
   
// 1. 创建信号
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(
id <RACSubscriber> subscriber ) {
       
       
        //系统会自动取消订阅者,这里被强引用,return 里不能取消订阅
        _subscriber = subscriber;
       
        
// 3. 发送信号
        [subscriber sendNext:
@"123" ];
      
       
return [RACDisposable disposableWithBlock:^{
          
// 只要信号取消订阅就会来这
           
// 清空资源
            NSLog(
@" 信号被取消订阅了 " );
        }];
    }];
   
   
// 2. 订阅信号
    RACDisposable *disposable = [signal subscribeNext:^(
id x) {
       
        NSLog(
@"%@" ,x);
       
    }];
   
// 1. 创建订阅者 , 保存 nextBlock
   
// 2. 订阅信号
   
   
// 默认一个信号发送数据完毕们就会主动取消订阅 .
   
// 只要订阅者在 , 就不会自动取消信号订阅
  
   // 取消订阅信号
    [disposable dispose];
}







RACSubject/RACReplaySubject
- ( void )RACReplaySubject
{
   
// 1. 创建信号
    RACReplaySubject *subject = [RACReplaySubject subject];
   
   
// 2. 订阅信号
    [subject subscribeNext:^(
id x) {
        NSLog(
@"%@" ,x);
    }];
   
// 遍历所有的值 , 拿到当前订阅者去发送数据
   
   
// 3. 发送信号
    [subject sendNext:@1];
    // [subject sendNext:@1];
    // RACReplaySubject 发送数据 :
   
// 1. 保存值
   
// 2. 遍历所有的订阅者 , 发送数据
   
   
   
// RACReplaySubject: 可以先发送信号 , 在订阅信号
}


- (
void )RACSubject
{
   
// 1. 创建信号
    RACSubject *subject = [RACSubject subject];
   
   
// 2. 订阅信号
   
   
// 不同信号订阅的方式不一样
   
// RACSubject 处理订阅 : 仅仅是保存订阅者
    [subject subscribeNext:^(
id x) {
        NSLog(
@" 订阅者一接收到数据 :%@" ,x);
    }];
   
   
// 3. 发送数据
    [subject sendNext:@1];
   
   
//    [subject subscribeNext:^(id x) {
   
//        NSLog(@" 订阅二接收到数据 :%@",x);
   
//    }];
   
// 保存订阅者
   
  
   
// 底层实现 : 遍历所有的订阅者 , 调用 nextBlock
   
   
// 执行流程 :
   
   
// RACSubject 被订阅 , 仅仅是保存订阅者
   
// RACSubject 发送数据 , 遍历所有的订阅 , 调用他们的 nextBlock
}









集合
- ( void )tuple
{
   
// 元组
    RACTuple *tuple = [RACTuple tupleWithObjectsFromArray:@[
@"213" , @"321" ,@1]];
   
NSString *str = tuple[0];
   
    NSLog(
@"%@" ,str);

}

- ( void )arr
{
   
// 数组
   
NSArray *arr = @[ @"213" , @"321" ,@1];
   
   
// RAC 集合
   
//   RACSequence *sequence = arr.rac_sequence;
   
//
   
//    // 把集合转换成信号
   
//    RACSignal *signal = sequence.signal;
   
//
   
//    // 订阅集合信号 , 内部会自动遍历所有的元素发出来
   
//    [signal subscribeNext:^(id x) {
   
//        NSLog(@"%@",x);
   
//    }];
   
    [arr.rac_sequence.signal subscribeNext:^(
id x) {
        NSLog(
@"%@" ,x);
    }];
}

- ( void )dict
{
   
   
// 字典
   
NSDictionary *dict = @{ @"account" : @"aaa" , @"name" : @"xmg" , @"age" :@18};
   
   
// 转换成集合
    [dict.rac_sequence.signal subscribeNext:^(RACTuple *x) {
       
//       NSString *key = x[0];
       
//        NSString *value = x[1];
       
//        NSLog(@"%@ %@",key,value);
       
       
// RACTupleUnpack: 用来解析元组
       
// 宏里面的参数 , 传需要解析出来的变量名
       
// = 右边 , 放需要解析的元组
        RACTupleUnpack(NSString *key,NSString *value) = x;
       
        NSLog(
@"%@ %@" ,key,value);
    }];
}

应用:数组转模型
Flag.h
@property ( nonatomic , strong ) NSString *name;

@property ( nonatomic , strong ) NSString *icon;

+ (instancetype)flagWithDict:(NSDictionary *)dict;


Flag.m
+ ( instancetype )flagWithDict:( NSDictionary *)dict
{
   
Flag *flag = [[ self alloc] init];
   
    [flag setValuesForKeysWithDictionary:dict];
   
   
return flag;
}

ViewController.m
- ( void )viewDidLoad {
    [
super viewDidLoad];
   
// Do any additional setup after loading the view, typically from a nib.
    


    // 解析 plist 文件
  
NSString *filePath = [[ NSBundle mainBundle] pathForResource: @"flags.plist" ofType: nil ];
   
NSArray *dictArr = [ NSArray arrayWithContentsOfFile:filePath];
   
//    NSMutableArray *arr = [NSMutableArray array];
//    [dictArr.rac_sequence.signal subscribeNext:^(NSDictionary *x) {
//        Flag *flag = [Flag flagWithDict:x];
//        [arr addObject:flag];
//    }];
   
   
// 高级用法
   
// 会把集合中所有元素都映射成一个新的对象
  
NSArray *arr = [[dictArr.rac_sequence map:^ id (NSDictionary *value) {
       
// value: 集合中元素
       
// id: 返回对象就是映射的值
       
return [Flag flagWithDict:value];
    }] array];
   
    NSLog(
@"%@" ,arr);
   
}





使用场景
代理(对比)
方法一 RACSubject(可传值)
DDCarTypeCell.h  
@protocol CarTypeDelegate < NSObject >

- (
void )changeTaxiCostLabelWithZoomLevel:( NSUInteger )zoomLevel;

@end

@interface DDCarTypeCell : UITableViewCell

@property ( nonatomic , assign ) id < CarTypeDelegate >delegate;

reactiveCocoa
@property ( nonatomic , strong ) RACSubject *btnClickSignal;

@end


DDCarTypeCell.m
- ( instancetype )initWithCoder:( NSCoder *)aDecoder{
   
self = [ super initWithCoder:aDecoder];
 if([_delegaterespondsToSelector:@selector(changeTaxiCostLabelWithZoomLevel:)]) {
        [ _delegate changeTaxiCostLabelWithZoomLevel :16];
    }

reactiveCocoa
[ self sendNext:@16 ];


    return self ;
}

reactiveCocoa
- (RACSubject *)btnClickSignal
{
   
if (_btnClickSignal == nil ) {
        _btnClickSignal = [RACSubject subject];
    }
   
return _btnClickSignal;
}




ViewController.m

@interface DDTaxiViewController () <CarTypeDelegate>
- ( void )viewDidLoad {
    [
super viewDidLoad];
UITableViewCell *cell = [UITableViewCell alloc] init];
cell.delegate = self;


reactiveCocoa
   // 订阅信号
    [cell.btnClickSignal subscribeNext:^(id x) {
      
        NSLog(
@"%@" ,x);
    }];

 
}


#pragma  mark - carType delegate
- ( void )changeTaxiCostLabelWithZoomLevel:( NSUInteger )zoomLevel{
 
}





方法二 rac_signalForSelector(不需传值)
RedVIew.h
//私有方法
- ( IBAction )btnClick:( id )sender
{
//    NSLog(@" 按钮被点击 l");
// 通知控制器做事情
   
}


ViewController.m
@property ( weak , nonatomic ) IBOutlet RedVIew *redView;
@property (weak,nonatomic)IBOutletUIButton *btn;
@property ( weak , nonatomic ) IBOutlet UITextField *textField;

- ( void )delegate
{
   
// 1. 代替代理 :1.RACSubject 2.rac_signalForSelector
   
// 只要传值 , 就必须使用 RACSubject
    [[_redView rac_signalForSelector:
@selector (btnClick:)] subscribeNext:^( id x) {
        NSLog(
@" 控制器知道按钮被点击 " );
    }];
   
   
// RAC:
   
// 把控制器调用 didReceiveMemoryWarning 转换成信号
   
// rac_signalForSelector: 监听某对象有没有调用某方法
   
//    [[self rac_signalForSelector:@selector(didReceiveMemoryWarning)] subscribeNext:^(id x) {
   
//        NSLog(@" 控制器调用 didReceiveMemoryWarning");
   
//    }];
}

kvo 
好处:高聚合,添加观察和改变执行的方法在一起,并且不用判断监听的值


ViewController.m

需要引入头  #import "NSObject+RACKOVWrapper.h"
 [_redView rac_observeKeyPath: @"frame" options:NSKeyValueObservingOptionNew observer: nil block:^( id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
}];

  [_redView rac_observeKeyPath: @"bounds" options:NSKeyValueObservingOptionNew observer: nil block:^( id value, NSDictionary *change, BOOL causedByDealloc, BOOL affectedOnlyLastComponent) {
      
       
    }];
   
   
  [[_redView rac_valuesForKeyPath:@"frame" observer:nil] subscribeNext:^(id x) {
      // x: 修改的值  
        NSLog( @"%@" ,x);
    }];
    
监听事件
 [[_btn rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^( id x) {
        NSLog(
@" 按钮点击了 " );
    }];


代替通知
[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardWillShowNotification object: nil ] subscribeNext:^( id x) {
       
        NSLog(
@"%@" ,x);
    }];

监听文本框
[_textField.rac_textSignal subscribeNext:^( id x) {
      
        NSLog(
@"%@" ,x);
    }];



处理当界面有多次请求时,需要都获取到数据时,才能展示界面
    
  - ( void )liftSelector
{
   
// 当一个界面有多次请求时候 , 需要保证全部都请求完成 , 才搭建界面
   
   
// 请求热销模块
    RACSignal *hotSignal = [RACSignal createSignal:^RACDisposable *(
id <RACSubscriber> subscriber) {
       
       
// 请求数据
       
// AFN
        NSLog(
@" 请求数据热销模块 " );
       
        [subscriber sendNext:
@" 热销模块的数据 " ];
       
       
return nil ;
    }];
   
   
// 请求最新模块
    RACSignal *newSignal = [RACSignal createSignal:^RACDisposable *(
id <RACSubscriber> subscriber) {
       
// 请求数据
        NSLog(
@" 请求最新模块 " );
       
        [subscriber sendNext:
@" 最新模块数据 " ];
       
       
return nil ;
    }];
   
   
// 数组 : 存放信号
   
// 当数组中的所有信号都发送数据的时候 , 才会执行 Selector
   
// 方法的参数 : 必须跟数组的信号一一对应
   
// 方法的参数 ; 就是每一个信号发送的数据
    [
self rac_liftSelector: @selector (updateUIWithHotData:newData:) withSignalsFromArray:@[hotSignal,newSignal]];
}

- (
void )updateUIWithHotData:( NSString *)hotData newData:( NSString *)newData
{
   
// 拿到请求的数据
    NSLog(
@" 更新 UI %@ %@" ,hotData,newData);
}








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值