为了支持这种模型,ReactiveCocoa自己持有全局的所有信号。如果一个signal有一个或多个订阅者,那这个signal就是活跃的。如果所有的订阅者都被移除了,那这个信号就能被销毁了。更多关于ReactiveCocoa如何管理这一过程,参见文档Memory Management。
上面说的就引出了最后一个问题:如何取消订阅一个signal?在一个completed或者error事件之后,订阅会自动移除(马上就会讲到)。你还可以通过RACDisposable 手动移除订阅。
RACSignal的订阅方法都会返回一个RACDisposable实例,它能让你通过dispose方法手动移除订阅。下面是一个例子:
RACSignal *backgroundColorSignal = [self.searchText.rac_textSignal map:^id(NSString *text) { return [self isValidSearchText:text] ? [UIColor whiteColor] : [UIColor yellowColor]; }]; RACDisposable *subscription = [backgroundColorSignal subscribeNext:^(UIColor *color) { self.searchText.backgroundColor = color; }]; // at some point in the future ... [subscription dispose];?
你会发现这个方法并不常用到,但是还是有必要知道可以这样做。
注意:根据上面所说的,如果你创建了一个管道,但是没有订阅它,这个管道就不会执行,包括任何如doNext: block的附加操作。
ReactiveCocoa已经在幕后做了很多事情,这也就意味着你并不需要太多关注signal的内存管理。但是还有一个很重要的内存相关问题你需要注意。
看一下你刚才添加的代码:
[[self.searchText.rac_textSignal map:^id(NSString *text) { return [self isValidSearchText:text] ? [UIColor whiteColor] : [UIColor yellowColor]; }] subscribeNext:^(UIColor *color) { self.searchText.backgroundColor = color; }];?
subscribeNext:block中使用了self来获取text field的引用。block会捕获并持有其作用域内的值。因此,如果self和这个信号之间存在一个强引用的话,就会造成循环引用。循环引用是否会造成问题,取决于self对象的生命周期。如果self的生命周期是整个应用运行时,比如说本例,那也就无伤大雅。但是在更复杂一些的应用中,就不是这么回事了。
为了避免潜在的循环引用,Apple的文档中建议获取一个self的弱引用。用本例来说就是下面这样的:
__weak RWSearchFormViewController *bself = self; // Capture the weak reference [[self.searchText.rac_textSignal map:^id(NSString *text) { return [self isValidSearchText:text] ? [UIColor whiteColor] : [UIColor yellowColor]; }] subscribeNext:^(UIColor *color) { bself.searchText.backgroundColor = color; }];?
在上面的代码中,__weak修饰符使bself成为了self的一个弱引用。注意现在subscribeNext:block中使用bself变量。不过这种写法看起来不是那么优雅。
ReactiveCocoa框架包含了一个语法糖来替换上面的代码。在文件顶部添加下面的代码:
#import "RACEXTScope.h"?
然后把代码替换成下面的:
@weakify(self) [[self.searchText.rac_textSignal map:^id(NSString *text) { return [self isValidSearchText:text] ? [UIColor whiteColor] : [UIColor yellowColor]; }] subscribeNext:^(UIColor *color) { @strongify(self) self.searchText.backgroundColor = color; }];?