【问题标题】:self becomes nil even if strongify in Reactivecocoa即使在 Reactivecocoa 中加强,self 也会变为 nil
【发布时间】:2016-02-22 15:36:57
【问题描述】:

我猜代码本身解释了一切,所以看看下面的代码。

-(RACSignal *)bossMethod {
    @weakify(self)
    return [[[self method1] flattenMap:^RACStream *(id value) {
        @strongify(self)
        return [self method2];
    }] flattenMap:^RACStream *(id value) {
        @strongify(self)
        return [self method3];
    }];
}

基本上,我将信号链接起来以逐步执行多种方法。但是方法 3 根本没有被调用。所以我坚持下去,发现 self 在[self method3] 即将接到电话的时候变成了 nil。它是怎么发生的?为什么@strongify(self) 在这种情况下不起作用?如有任何建议,我将不胜感激。

【问题讨论】:

  • 这是预期的行为,@weakify 让你弱捕获自我,@strongify 将弱变量变为强变量。所以如果弱变量本身是nil,那么强变量也一定是nil。
  • 不,我不这么认为。如果 self 本身为 nil,则不应运行任何方法,但方法 1 和方法 2 运行 find 但不运行方法 3
  • 如果[self method2]返回的信号在self的dealloc之后存活并发送一些值,这是完全可能的。

标签: ios signals reactive-cocoa


【解决方案1】:

self 可能在执行第一个和第二个flattenMap 块之间被设置为nil(因为最后一个strongreference 对象被self 删除)。

一般@strongify 不保证变量不为零。它只保证它不会突然设置为nil inside 范围(在您的情况下,在flattenMap 块内)。

假设您没有使用过@strongify,并且有以下代码:

  @weakify(self)
    return [[self method1] flattenMap:^RACStream *(id value) {
        [self doSomethingPossiblyLong];  //1
        return [self method2]; //2
    }];

现在在传递给flattenMap 的块内,您执行两个操作。第一个(1)做一些(可能很长)计算。第二个 (2) 做的事情取决于 (1) 的结果。而且您处理的是多线程代码,因此在这些计算期间(或之后)另一个线程可以启动。

在第二个线程中,可能会删除对对象的最后一个强引用,即您的 self。例如,它可能是 UI(主)线程,它可以关闭拥有该对象的视图控制器。然后 ARC 将完成它的工作,将对该对象的所有弱引用转换为 nil

现在执行回到flattenMap 块,回到这一行:

return [self method2]; //2

但是self 变成了nil。之前所有的计算都是徒劳的,太糟糕了。

在这种情况下,使用@strongify 是有意义的。因为您要确保在flattenMapblock 中的代码开始执行后,对self(或包装在@strongify 宏中的其他变量)的引用不会是nil,直到块的最后.

请注意,在您发布的代码中,flattenMap 中只有单个方法调用,因此您并没有真正从@strongify 中受益。但是使用它可能仍然是一个好习惯,因此当您在块内添加更多调用 self 的方法时,您不会忘记它。

【讨论】:

  • 如果@strongify(self) 不能保证 self 不为零,那么使用@weakify 和@strongify 有什么意义呢?这样做,您有代码无法运行的风险。如果不使用@weakify 和@strongify,那么您可能会进行保留循环。
  • 您绝对应该使用@weakify(self) 来避免保留循环。但是@strongify(self) 不是强制性的。在许多情况下,仅使用 @weakify(self) 就足够了。正如我在回答中提到的那样,当在一个块内self 调用多个方法时,您可能想要使用它。 @strongify 保证如果第一个方法在self 不是nil 时执行,则此块中 中的所有其他方法也将以非零self 调用。另请参阅此答案中的讨论:stackoverflow.com/a/28809324/2128900
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多