ReactiveCocoa:当没有人订阅它时释放RACSignal

时间:2015-11-20 12:03:17

标签: ios reactive-cocoa

在我的班级中,应用程序的其他部分可能会观察到一些值。可以读取这些值并将其写入数据库。

我有一个保留一些RACS主题的集合。

当一个对象需要观察一个值V1时,我会为它创建一个RACSignal,将其命名为S1,之后如果任何其他对象也感兴趣V1,我也会给它V1,这样当S1改变时,我可以调用[RACSubject sendNext:]来通知对它感兴趣的对象。

但是有一个问题,我不知道何时发布S1,因为我不知道在没有订阅S1的对象时如何得到通知。

有没有办法做到这一点?

2 个答案:

答案 0 :(得分:1)

我在心理上将你问题的一部分重写为以下内容(我的修改用斜体字),因为我认为原来的措辞有一些拼写错误:

  

当一个对象需要观察一个值V1时,我会为它创建一个 RACSubject ,将其命名为S1,以后再命名为V1对象也对S1感兴趣,我也会给它 V1 ,这样当 [RACSubject sendNext:] 更改时,我可以调用RACSubject通知对其感兴趣的对象。

如果这是不正确的解释,请忽略此答案。

如果您没有自己明确保留信号,ReactiveCocoa will automatically reclaim it when it runs out of subscribers。相关摘录:

  
      
  1. 创建的信号会自动添加到一组全局活动信号中。
  2.   
  3. 信号将等待主运行循环的单次传递,然后如果没有订户则从活动集中移除自身。除非信号以某种方式保留,否则它将在此时解除分配。
  4.   
  5. 如果在该运行循环迭代中订阅了某些内容,则该信号将保留在该集合中。
  6.   
  7. 稍后,当所有订阅者都离开后,再次触发第2步。
  8.   

但是有一个问题:这不适用于RACSignal *autoretainedSignal = [subject map:^(id x) { return x; }] 。它们不会添加到全局活动信号集中。

但是,您可以应用... 解决方法以获得良好的自动保留行为。

autoretainedSignal

只要您只订阅RACSubject,而不是基础 <?php if(!isset($_SESSION['username'])) { die("Please login"); } else { echo "what user can see"; } ?> ,就可以利用正常信号获得的自动保留行为。

那你怎么坚持下去呢?如果您只有一个信号,您在缓存/共享中感兴趣,您可以将它存储在弱属性中。如果您正在动态管理多个属性,那么具有弱存储空间的NSMapTable就是您的朋友。

您需要保留底层主题(因此您可以在其上发送事件)和派生信号(以便您可以将其提供给订阅者)。只要衍生信号具有订阅者,它就会使其基础主题保持活跃状态​​,并且一旦订阅者用完,它和它的主题都将被释放。

答案 1 :(得分:-1)

我找到了你的想法:)

 @property (nonatomic,assign) NSInteger countOfSubscribers = 0;

稍后在您的代码中

    RACSignal *s; // here is your target signal

    [[s rac_signalForSelector:@selector(subscribeNext:)]
     subscribeNext:^(id x) {
         self.countOfSubscribers++;
     }];


    [[[s rac_signalForSelector:@selector(subscribeNext:)] rac_willDeallocSignal]
     subscribeNext:^(id x) {
         self.countOfSubscribers--;
     }];

主要想法是订阅'subscribeNext:'方法,并在删除原始订阅者时rac_willDeallocSignal 会叫。

这不是完全测试的片段,但我希望这可以帮助您找到正确的方向。