内存管理
ReactiveCocoa自己持有全局的所有信号,如果一个信号有一个或多个订阅者,那么这个信号就是活跃的;如果所有的订阅者都被移除了,那么这个信号就能被销毁了。
那么如何取消订阅一个信号呢?
使用dispose
方法
RACDisposable *singal = [self.searchTextField.rac_textSignal subscribeNext:^(id x) {
NSLog(@"value=%@", x);
}];
//在需要取消的时候调用
[singal dispose];
循环引用问题
先看一个例子
[[self.searchTextField.rac_textSignal map:^id(NSString *text) {
return text.length > 5 ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
self.searchTextField.backgroundColor = color;
}];
subscribeNext:block中使用了self来获取text field的引用。block会捕获并持有其作用域内的值。因此,如果self和这个信号之间存在一个强引用的话,就会造成循环引用。循环引用是否会造成问题,取决于self对象的生命周期。如果self的生命周期是整个应用运行时,比如说本例,那也就无伤大雅。但是在更复杂一些的应用中,就不是这么回事了。
为了避免潜在的循环引用,Apple建议的做法如下
__weak ViewController *blockSelf = self;
[[self.searchTextField.rac_textSignal map:^id(NSString *text) {
return text.length > 5 ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
blockSelf.searchTextField.backgroundColor = color;
}];
在RAC中还可以这么做
@weakify(self)
[[self.searchTextField.rac_textSignal map:^id(NSString *text) {
return text.length > 5 ? [UIColor whiteColor] : [UIColor redColor];
}]
subscribeNext:^(UIColor *color) {
@strongify(self)
self.searchTextField.backgroundColor = color;
}];
上面的@weakify 和 @strongify 语句是在Extended Objective-C库中定义的宏,也被包括在ReactiveCocoa中。@weakify宏让你创建一个弱引用的影子对象(如果你需要多个弱引用,你可以传入多个变量),@strongify让你创建一个对之前传入@weakify对象的强引用。
最后需要注意的一点,在block中使用实例变量时请小心谨慎。这也会导致block捕获一个self的强引用。你可以打开一个编译警告,当发生这个问题时能提醒你。在项目的build settings中搜索“retain”,找到下面显示的这个选项:
线程
切换到主线程更新UI,使用deliverOn:[RACScheduler mainThreadScheduler]
这种方式实现,比如在后台下载图片,完成后到主界面显示图片
- (RACSignal *)downloadImage
{
RACScheduler *scheduler = [RACScheduler schedulerWithPriority:RACSchedulerPriorityBackground];
NSString *urlString = @"http://img1.qunarzz.com/sight/p0/1603/b0/b014d9f8ab2a5afb90.water.jpg_1190x550_8d26b98e.jpg";
return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
UIImage *image = [UIImage imageWithData:data];
[subscriber sendNext:image];
[subscriber sendCompleted];
return nil;
}] subscribeOn:scheduler];
}```
[[[self downloadImage] deliverOn:[RACScheduler mainThreadScheduler]]
subscribeNext:^(UIImage *image) {
NSLog(@"Thread:%@ image:%@", [NSThread currentThread], image);
}];
##参考链接
[ReactiveCocoa入门教程2](http://benbeng.leanote.com/post/ReactiveCocoaTutorial-part2)
网友评论