如果我在一个区块内使用dispatch_queue
怎么办?什么是避免保留周期的正确方法,但也避免过早释放弱指针?
__weak MyClass *weakSelf = self;
[apiClient fetchData:^(...) {
typeof(self) selfref = weakSelf;
dispatch_async(dispatch_get_main_queue(), ^{
// using selfref here
}
});
这是正确的做法还是我错过了什么?如何确保正确处理所有内容并且不会发生保留周期?我不能在这里做一些dealloc测试...
我的问题与this here不同,因为我在第一个区块内有另一个区块。我问的是如何处理这种情况。
答案 0 :(得分:8)
首先澄清一下,只有当对象指向自身时才会出现保留周期!这通常发生在对象的某些属性具有强引用对象(obj持有属性,其中包含对象...)时,无论是通过块还是委托。
Blocks捕获对从外部作用域传递给它们的任何对象的强引用 - 包括self。当你声明一个块并执行它时,这不是问题,因为块是在方法中声明的,而ARC是将在方法结束时解除它:
-(void)test
{
void(^aBlock)() = ^{
[self someMethod];
};
aBlock();
}
但是当您将此块存储到以后的某些用法(例如回调)时会出现问题,如下所示:
@property(nonatomic, copy) void(^aBlock)();
-(void)test
{
_aBlock = ^{
[self someMethod];
};
}
我们现在在ClassA中有一个强引用(我们的属性aBlock),它对ClassA有强引用(在aBlock实现中通过self)。现在我们遇到了一个问题 - 这个类指向自己,永远不会被释放!如果我们按如下方式重写,那就更加明显了:
-(void)test
{
self.aBlock = ^{
[self someMethod];
};
}
现在让我们打破你的代码只是为了确保我们正在谈论相同的事情:
__weak MyClass *weakSelf = self;
[apiClient fetchData:^(...) {
typeof(self) selfref = weakSelf; <---- outer block
dispatch_async(dispatch_get_main_queue(), ^{
// using selfref here <---- inner block
}
});
一步一步走:
希望这一切对你有意义,并且你将与ObjC块一起光荣地战斗;)
答案 1 :(得分:0)
据我所知,当你使用block时,你不应该使用强参考。但如果你需要&#34; self&#34;在您的代码中,您可以像scanerio一样声明弱属性。我认为,你的代码工作得很好。
为了确保,您可以轻松地测试覆盖dealloc方法kust,如下所示。
-(void)dealloc{
NSLog(@"Deallocated");
}
请复制并粘贴下面的代码段,然后运行您的代码。如果你看到&#34; Deallocated&#34;您的控制台中的单词,您没有保留周期。您也可以通过个人资料观看保留周期。
答案 2 :(得分:-1)
使用以下代码管理block
的最佳方式。
__weak MyClass *weakSelf = self;
[apiClient fetchData:^(...) {
__strong MyClass * selfref = weakSelf;
dispatch_async(dispatch_get_main_queue(), ^{
// using selfref here
}
});
这里__strong
是为了保证当weakSelf
在执行块的第一行时仍处于活动状态时,它将继续存在以执行块的其余部分。所以如果你在另一个block
内使用该变量,那就不会有任何问题。因为main block
范围在inner block
执行时完成。
此处typeof(self) selfref = weakSelf;
等于__strong MyClass * selfref = weakSelf;
希望这对你有所帮助。