移动端开发

ReactiveCocoa 入门知识——归总篇

2017-06-06  本文已影响64人  陈雨尘

ReactiveCocoa (RAC) 是一个Cocoa框架,受Functional Reactive Programming启发。它提供Api合成变换(composing and transforming)随着时间改变的数据流
介绍

ReactiveCocoa来源于functional reactive programming(Input and Output)。区别于使用不断变化修改的变量,RAC提供了“事件流”,通过 SignalSignalProducer 类型来表示, 它们随着时间发送值。事件流统一了Cocoa用于事件和异步处理的常用模式,包括:
委托方法
回调blocks
通知
控件的actions和响应事件链
Futures and promises
Key-value observing (KVO)

因为这些不同的机制能够用一种相同的方式处理,可以很容易的声明成链(chain)并且把它们联合在一起,用更少的代码和状态连接它们。
基本使用


1.创建信号

方法1:

   RACSubscriber:表示订阅者的意思,用于发送信号,这是一个协议,不是一个类,只要遵守这个协议,并且实现方 v     法才 能成为订阅者。通过create创建的信号,都有一个订阅者,帮助他发送数据。
 RACDisposable:用于取消订阅或者清理资源,当信号发送完成或者发送错误的时候,就会自动触发它。
RACSignal *siganl = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
    // block调用时刻:每当有订阅者订阅信号,就会调用block。
    // 2.发送信号
    [subscriber sendNext:@1];
    // 如果不在发送数据,发送信号完成,内部会自动调用[RACDisposable disposable]取消订阅信号。
    [subscriber sendCompleted];
    return [RACDisposable disposableWithBlock:^{
        // block调用时刻:当信号发送完成或者发送错误,就会自动执行这个block,取消订阅信号。
        // 执行完Block后,当前信号就不在被订阅了。
        NSLog(@"信号被销毁");
    }];
}];
// 3.订阅信号,才会激活信号.
[siganl subscribeNext:^(id x) {
    // block调用时刻:每当有信号发出数据,就会调用block.
    NSLog(@"接收到数据:%@",x);
}];
   2017-06-06 16:34:27.387 ReactiveCocoaDome[17827:6819312] 接收到数据:1
   2017-06-06 16:34:27.387 ReactiveCocoaDome[17827:6819312] 信号被销毁

方法2:

 // 1.创建信号
  RACSubject *subject = [RACSubject subject];
 // 2.订阅信号
  [subject subscribeNext:^(id x) {
    // block调用时刻:当信号发出新值,就会调用.
    NSLog(@"第一个订阅者%@",x);
 }];
 [subject subscribeNext:^(id x) {
    // block调用时刻:当信号发出新值,就会调用.
    NSLog(@"第二个订阅者%@",x);
}];
// 3.发送信号
 [subject sendNext:@"1"];
2017-06-06 16:34:27.388 ReactiveCocoaDome[17827:6819312] 第一个订阅者1
2017-06-06 16:34:27.388 ReactiveCocoaDome[17827:6819312] 第二个订阅者1

方法3:

  // RACReplaySubject使用步骤:
  // 1.创建信号 [RACSubject subject],跟RACSiganl不一样,创建信号时没有block。
  // 2.可以先订阅信号,也可以先发送信号。
  // 2.1 订阅信号 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
  // 2.2 发送信号 sendNext:(id)value
  // RACReplaySubject:底层实现和RACSubject不一样。
  // 1.调用sendNext发送信号,把值保存起来,然后遍历刚刚保存的所有订阅者,一个一个调用订阅者的nextBlock。
  // 2.调用subscribeNext订阅信号,遍历保存的所有值,一个一个调用订阅者的nextBlock
  // 如果想当一个信号被订阅,就重复播放之前所有值,需要先发送信号,在订阅信号。
  // 也就是先保存值,在订阅值。

// 1.创建信号
RACReplaySubject *replaySubject = [RACReplaySubject subject];

// 2.发送信号
[replaySubject sendNext:@1];
[replaySubject sendNext:@2];
[replaySubject sendCompleted];

// 3.订阅信号
[replaySubject subscribeNext:^(id x) {
    
    NSLog(@"第一个订阅者接收到的数据%@",x);
}];

// 订阅信号
[replaySubject subscribeNext:^(id x) {
    
    NSLog(@"第二个订阅者接收到的数据%@",x);
}];


RACDisposable * dispose = [RACDisposable disposableWithBlock:^{
    NSLog(@"replaySubject 销毁了");
  
}];
RACCompoundDisposable * compoundDispose = [RACCompoundDisposable compoundDisposableWithDisposables:@[dispose]];
[replaySubject didSubscribeWithDisposable:compoundDispose];
 2017-06-06 16:34:27.550 ReactiveCocoaDome[17827:6819312] 第一个订阅者接收到的数据1
 2017-06-06 16:34:27.550 ReactiveCocoaDome[17827:6819312] 第一个订阅者接收到的数据2
 2017-06-06 16:34:27.551 ReactiveCocoaDome[17827:6819312] 第二个订阅者接收到的数据1
 2017-06-06 16:34:27.551 ReactiveCocoaDome[17827:6819312] 第二个订阅者接收到的数据2
 2017-06-06 16:34:27.551 ReactiveCocoaDome[17827:6819312] replaySubject 销毁了

当然 RACReplaySubject *replaySubject = [RACReplaySubject replaySubjectWithCapacity:1];
通过这种方式创建的 则指定了默认的储存值是1个
打印的 则为

 2017-06-06 16:51:00.570 ReactiveCocoaDome[18117:6914095] 第一个订阅者接收到的数据2
 2017-06-06 16:51:00.570 ReactiveCocoaDome[18117:6914095] 第二个订阅者接收到的数据2
2.针对不同对象的基本使用方法

*字典转模型 RAC高级写法 *

  // map:映射的意思,目的:把原始值value映射成一个新值
  // array: 把集合转换成数组
  // 底层实现:当信号被订阅,会遍历集合中的原始值,映射成新值,并且保存到新的数组里。
  NSArray *MMs = [[dictArr.rac_sequence map:^id(id value) {
     return [MM MMwithDic:value];
     }] array];
3.其他常用
4.常用宏
    // RAC 用于给某个对象的属性绑定
RAC(self.sendBut.titleLabel,text) = self.textF.rac_textSignal;

//RACObserve(self, name):监听某个对象的某个属性,返回的是信号。
[RACObserve(self.view, center)subscribeNext:^(id x) {
    NSLog(@"%@",x);
}];
@weakify(self); @strongify(self);
// RACTuplePack:把数据包装成RACTuple(元组类)
// 把参数中的数据包装成元组
RACTuple *tuple1 = RACTuplePack(@10,@20);
 //RACTupleUnpack:把RACTuple(元组类)解包成对应的数据。
  // 把参数中的数据包装成元组
  RACTuple *tuple = RACTuplePack(@"img",@20);
 // 解包元组,会把元组的值,按顺序给参数里面的变量赋值
 // name = @"xmg" age = @20
 RACTupleUnpack(NSString *name,NSNumber *age) = tuple;
5.项目中使用示例

网络请求
- (RACSubject *)POST:(NSString *)path parameters:(id)parameters
{
RACReplaySubject *signal = [RACReplaySubject replaySubjectWithCapacity:1];
NSURLSessionDataTask *task = [[PR_HTTPSessionManager defaultManager] POST:path parameters:[[self class] addPublicParameters:parameters] success:^(NSURLSessionDataTask *task, id responseObject){
NSDictionary * responseDict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];

        NSError *error = [[self class] errorForResponseObject:responseDict];
        if (error) {
             [signal sendError:error];
        } else {
            id data = responseDict[@"results"];
            [signal sendNext:data];
            [signal sendCompleted];
        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        
        [signal sendError:[[self class] localizedError:error]];
    }];
  
@weakify(task);
RACDisposable * dispose = [RACDisposable disposableWithBlock:^{
    @strongify(task);
    [task cancel];
}];

RACCompoundDisposable * compoundDispose = [RACCompoundDisposable compoundDisposableWithDisposables:@[dispose]];
[signal didSubscribeWithDisposable:compoundDispose];

return signal;
}


  + (RACSignal *)updateUserInfo:(NSDictionary *)params {
RACSignal *signal = [RACSignal empty];
NSString *method = @"xxxxxx";
signal =
    [[PR_HTTPSessionManager defaultManager] POST:method parameters:params];
return signal;
}  

一段赋值代码

 @weakify(self);
 RAC(self.suggestTitleLabel,text) = RACObserve(self, viewModel.title);
 [[RACObserve(self, viewModel) ignore:nil] subscribeNext:^(DoctorSuggestTableViewCellModel  *cellViewModel) {
    @strongify(self);
    [self.textField setText:cellViewModel.contentString];
    self.suggestCollectionView.allowsMultipleSelection = cellViewModel.allowsMultipleSelection;
    
    [[self.textField.rac_textSignal takeUntil:self.rac_prepareForReuseSignal] subscribeNext:^(id x) {
        @strongify(self);
        self.viewModel.contentString = x;
    }];
     [[RACObserve(self.otherTextView,content) takeUntil:self.rac_prepareForReuseSignal]subscribeNext:^(id x)       {
        @strongify(self);
        self.viewModel.descriptionString = x;
    }];

}]; 

当然还有很多使用到的地方就不在累述 Dome地址

以上都是入门级的使用,希望可以对你有所帮助!

上一篇 下一篇

猜你喜欢

热点阅读