以下代码来自Apple(source here)提供的LazyTableImages示例代码。
在他们的完成块中,他们引用了self,这应该会导致一个保留周期...但是我没有在Xcode中得到警告,而在我的类似代码中我会这样做。
这是对的吗?
也许我错过了这个细微之处。
- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.appRecord = appRecord;
[iconDownloader setCompletionHandler:^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// Display the newly loaded image
cell.imageView.image = appRecord.appIcon;
// Remove the IconDownloader from the in progress list.
// This will result in it being deallocated.
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
[self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
}
}
答案 0 :(得分:0)
self
没有指向iconDownloader
的强指针。它的创建和范围只适用于这种方法:
IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
如果iconDownloader
是强属性(self.iconDownloader
),则Xcode会检测到强大的参考周期。
答案 1 :(得分:0)
没有警告,因为编译器还不能检测所有可能的保留周期。
例如:
- (void)foo
{
_block = ^ { [self done]; }; // Warning: Possible retain cycle
DSGenericBlock foo = ^ { [self done] };
_block = foo; // No warning.
}
如果要将块直接分配给“self”的实例变量,则会出现“可能的保留周期”警告。相反,该块被分配给另一个对象,然后由self保留,因此编译器不检测循环(即使循环确实存在)。