ReactiveCocoa 学习 - 4

RAC中的内存管理的一些介绍

2016-06-11 | 阅读

Memory Management

RAC中得内存管理是很复杂的,但是这样做的目的是,使用者不用持有信号来驱动信号发送的过程.

除了那些会长期存在的信号,会被以属性的形式持有,一般不要去持有信号.

  1. 信号的创建后,会自动的添加到一个全局的信号集合中.
  2. 然后这个信号会等待一次 main run loop的执行,这时如果信号还是没有被订阅,那信号将被集合移除.如果信号没有在其他地方被持有,那信号将会在这个时候被释放.
  3. 如果信号被订阅了,那信号会在这个信号集合中被持有.
  4. 如果信号的所有订阅者都消失了,那会重复第二步操作,即再等待一个runloop周期.

Subscribers

当使用subscribeNext:error:completed:订阅信号时,隐式地创建了一个RACSubscriber对象.所以创建信号时使用的block所关联的对象会被订阅所持有.

Finite or Shore-Lived Signals

在RAC的内存关联中,一个重要的注意事项就是, 订阅会在 completion 或是error时终止,订阅者也会被移除.

这样,信号的生命周期也就会跟随事件流的逻辑生命周期.

Infinite Signals

会有一些不会自行结束的信号存在,所以需要disposable存在.

信号订阅的dispose操作,会移除所有关联的订阅者,而且也会释放该信号所占有的资源.

Signlas Derived from self

有些信号是有self衍生出来的.如 RACObserve()监听self的一个属性时,在subscribeNext使用self指针,就会形成一个引用环.

建议使用@weakify@strongify这两个宏来处理指针. 当对象不能使用weak时,使用 __unsafe_unretained@unsafeify.

但很多时候,有一种更好地写法来解决循环指针的问题,如对于一般写法:

@weakify(self);
[RACObserve(self, username) subscribeNext:^(NSString *username) {
    @strongify(self);
    [self validateUsername];
}];

实际上我们可以这样写:

[self rac_liftSelector:@selector(validateUsername:) withSignals:RACObserve(self, username), nil];

或者这样写 :

RACSignal *validated = [RACObserve(self, username) map:^(NSString *username) {
    // Put validation logic here.
    return @YES;
}];