我猜代码本身解释了一切,所以看看下面的代码。
-(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) 在这种情况下不起作用?如有任何建议,我将不胜感激。
Best Answer-推荐答案 strong>
self 可能在第一个和第二个 flattenMap block 执行之间被设置为 nil (因为最后一个 strong 对作为 self 的对象的引用已被删除)。
一般 @strongify 不保证变量不为零。它只保证它不会突然设置为 nil inside 范围(在你的情况下,在 flattenMap block 内)。
假设您没有使用过 @strongify 并且有以下代码:
@weakify(self)
return [[self method1] flattenMap:^RACStream *(id value) {
[self doSomethingPossiblyLong]; //1
return [self method2]; //2
}];
现在,在传递给 flattenMap 的 block 中,您执行两个操作。第一个(1)做一些(可能很长)计算。第二个 (2) 做的事情取决于 (1) 的结果。而且您处理的是多线程代码,因此在这些计算期间(或之后)另一个线程可以启动。
在第二个线程中,可能会删除对您的 self 对象的最后一个强引用。例如,它可能是 UI(主)线程,它可以关闭拥有该对象的 View Controller 。然后 ARC 将完成它的工作,将对这个对象的所有弱引用变为 nil 。
现在执行回到 flattenMap block ,到这一行:
return [self method2]; //2
但是self 变成了nil 。之前所有的计算都是徒劳的,太糟糕了。
在这种情况下,使用 @strongify 是有意义的。因为您要确保在 flattenMap block 中的代码开始执行后,对 self 的引用(或包装在 @strongify 中的其他变量宏) 直到 block 的最后才为 nil 。
请注意,在您发布的代码中,flattenMap 内只有单个方法调用,因此您并没有真正从 @strongify 中受益。但是使用它可能仍然是一个好习惯,因此当您在 block 内添加更多调用 self 的方法时,您不会忘记它。
关于ios - 即使在 Reactivecocoa 中加强,self 也会变为 nil,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/35557724/
|