在块中捕获自我(保留周期),并非总是如此?

时间:2013-07-27 18:19:03

标签: objective-c block

以下代码来自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];  
    }
}

2 个答案:

答案 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保留,因此编译器不检测循环(即使循环确实存在)。