reactiveCocoa实践一

来源:互联网 发布:独立分销商城源码 编辑:程序博客网 时间:2024/05/01 14:21
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:^(
idx) {
       
       
// nextBlock调用:只要订阅者发送数据就会调用
       
// nextBlock作用:处理数据,展示到UI上面
       
       
// x:信号发送的内容
        NSLog(
@"%@",x);
    }];
   
   
// 只要订阅者调用sendNext,就会执行nextBlock
   
// 只要订阅RACDynamicSignal,就会执行didSubscribe
    // 前提条件是RACDynamicSignal,不同类型信号






RACDisposable
@interfaceViewController()

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

@end

@implementationViewController

- (
void)viewDidLoad {
    [
superviewDidLoad];
   
// 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:^(
idx) {
       
        NSLog(
@"%@",x);
       
    }];
   
// 1.创建订阅者,保存nextBlock
   
// 2.订阅信号
   
   
// 默认一个信号发送数据完毕们就会主动取消订阅.
   
// 只要订阅者在,就不会自动取消信号订阅
  
  //取消订阅信号
    [disposable dispose];
}







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


- (
void)RACSubject
{
   
// 1.创建信号
    RACSubject *subject = [RACSubject subject];
   
   
// 2.订阅信号
   
   
// 不同信号订阅的方式不一样
   
// RACSubject处理订阅:仅仅是保存订阅者
    [subject subscribeNext:^(
idx) {
        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 
@protocolCarTypeDelegate <NSObject>

- (
void)changeTaxiCostLabelWithZoomLevel:(NSUInteger)zoomLevel;

@end

@interfaceDDCarTypeCell :UITableViewCell

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

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

@end


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

reactiveCocoa
[selfsendNext:@16];


    return self;
}

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




ViewController.m

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


reactiveCocoa
   // 订阅信号
    [cell.btnClickSignal subscribeNext:^(idx) {
      
        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)IBOutletRedVIew *redView;
@property (weak,nonatomic)IBOutletUIButton *btn;
@property (weak,nonatomic)IBOutletUITextField *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
   
// 方法的参数:必须跟数组的信号一一对应
   
// 方法的参数;就是每一个信号发送的数据
    [
selfrac_liftSelector:@selector(updateUIWithHotData:newData:) withSignalsFromArray:@[hotSignal,newSignal]];
}

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








0 0