使用RACChannel进行双向数据绑定
RACChannel 非常适合于视图和模型之间的双向绑定,在对方的属性或者状态更新时及时通知自己,达到预期的效果;我们可以使用 ReactiveCocoa 中内置的很多与 RACChannel 有关的方法,来获取开箱即用的 RACChannelTerminal ,当然也可以使用 RACChannelTo 通过 RACKVOChannel 来快速绑定类与类的属性。
RACChannelTo(self.viewModel, username) = self.usernameTextField.rac_newTextChannel;
定时器,可以代替Timer
//这里要加takeUntil条件限制一下否则当控制器pop后依旧会执行
[[[RACSignal interval:2 onScheduler:[RACScheduler mainThreadScheduler]] takeUntil:self.rac_willDeallocSignal ] subscribeNext:^(id x) {
NSLog(@"每两秒执行一次");
}];
RAC通知写法
//代替通知
//takeUntil会接收一个signal,当signal触发后会把之前的信号释放掉
[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIKeyboardDidShowNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
NSLog(@"键盘弹出");
}];
多个请求,统一处理结果
- (void)testRACSignal
{
// 创建信号A
RACSignal *signalA = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 处理信号
NSLog(@"%s 创建信号A", __FUNCTION__);
// 发送数据
[subscriber sendNext:@"热门商品"];
return nil;
}];
// 创建信号B
RACSignal *signalB = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber> _Nonnull subscriber) {
// 处理信号
NSLog(@"%s 创建信号", __FUNCTION__);
// 发送数据
[subscriber sendNext:@"最新商品"];
return nil;
}];
// RAC:就可以判断两个信号有没有都发出内容
// SignalsFromArray:监听哪些信号的发出
// 当signals数组中的所有信号都发送sendNext就会触发方法调用者(self)的selector
// 注意:selector方法的参数不能乱写,有几个信号就对应几个参数
// 不需要主动订阅signalA,signalB,方法内部会自动订阅
[self rac_liftSelector:@selector(updateUIWithHot: new:) withSignalsFromArray:@[signalA,signalB]];
}
- (void)updateUIWithHot:(NSString *)hot new:(NSString *)new
{
NSLog(@"%s hot = %@ , new = %@", __FUNCTION__, hot ,new);
}
重试
-(void)retry{
__block int flag = 0;
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
if (flag == 4){
[subscriber sendNext:@"1"];
[subscriber sendCompleted];
}else{
flag ++;
NSLog(@"flag= %d",flag);
[subscriber sendError:[NSError errorWithDomain:@"myerror " code:100 userInfo:nil]];
}
return nil;
}];
[[signal retry:5]subscribeNext:^(id x) {
NSLog(@"xxxx =%@",x);
}];
}
发送请求,捕获错误处理
例子:如果在请求返回token过期,需要重新获取token再继续重新请求
// 发送请求
RACSignal *requestSignal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSString *url = @"http://httpbin.org/ip";
[[AFHTTPRequestOperationManager manager] GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
[subscriber sendNext:responseObject];
[subscriber sendCompleted];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// token 过期
[subscriber sendError:error];
}];
return nil;
}];
[[requestSignal catch:^RACSignal *(NSError *error) {
// error捕获
return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// 模拟获取token请求
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[subscriber sendNext:@YES];
NSLog(@"subscriber sendNext...");
[subscriber sendCompleted];
});
return nil;
}] concat:requestSignal]; //RACSignal拼接,获取token之后再重新请求
}] subscribeNext:^(id x) {
// 请求正常返回的数据
NSLog(@"next =%@",x);
} completed:^{
NSLog(@"completed");
}];
搜索请求
使用节流器throttle,在0.3秒内使用最后一个输入text进行请求
[[[[[[self.textField.rac_textSignal throttle:0.3] distinctUntilChanged] ignore:@""] map:^id(id value) {
NSLog(@"value =%@",value);
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
// network request
[subscriber sendNext:value];
[subscriber sendCompleted];
return [RACDisposable disposableWithBlock:^{
// cancel request
}];
}];
}] switchToLatest] subscribeNext:^(id x) {// 如果不switchToLastest 则返回一个signal
NSLog(@"x = %@",x);
}];
网友评论