我有一个UIPageViewController的视图,并且在设置视图控制器的方法中,我使用了一个自我的线程安全实例:
__block typeof(self) threadedSelf = self;
[self.pageController setViewControllers:@[p]
direction:UIPageViewControllerNavigationDirectionReverse
animated:YES
completion:^(BOOL finished){
if (finished) {
[threadedSelf performSelectorOnMainThread:@selector(setNavTitleText) withObject:nil waitUntilDone:NO];
}
}];
完成块看起来类似于其他完成块,比如UIView动画方法,但这是第一个完成块,我必须创建一个块版本的self。为什么这种方法与其他完成回调不同?是因为这是一个实例方法,其中UIView动画是一个类(静态)方法吗?
答案 0 :(得分:1)
这不是一个线程安全问题,它是一个保留周期问题。块保留它们使用的对象。显然,从警告开始,self
会保留此块,因此,如果 使用/保留self
,那么您有一个保留周期。
你应该在你在块中使用的指针上使用__weak
限定符,例如:
__weak typeof(self) weakSelf = self;
__weak
和__block
经常用于出现在块中的变量,但它们有不同的用途。 __weak
限定符可防止块保留对象,这正是阻止保留周期所需的工具。 __block
限定符确实阻止了块保留对象,但其目的实际上是指示可以在块内更改对象(即,对块内对象所做的更改必须在块外部可见) 。那个不是你的例子中的情况。您引用self
但未修改指针(self = foo
)。因此,您应该使用__weak
限定符而不是__block
限定符。
在许多情况下,你既不需要限定词。仅当块实际由块内引用的对象保留时,才会有保留周期。通常,您将使用未拥有的任何对象保留的块,例如:
[UIView animateWithDuration:0.2 animations:^{
[self makeSomeChangesToBeAnimated];
}];
此处动画块可以安全地引用self
而没有限定符,因为self
不会保留该块。它可能由 else 保留,但不能由self
保留,因此您无需使用__weak
限定符。
答案 1 :(得分:0)
如果self
保留了引用self
的块,我们会有一个保留周期。您试图避免的警告告诉您可能会发生这种情况。我不知道这是不是真的,但是,在明确警告的情况下,我没有机会:我使用“弱强舞”将self
的弱版本传递到块中。