【发布时间】:2013-03-14 04:10:37
【问题描述】:
我想为表格视图中的每一行下载图像,所以我编写了一个方法来使用 block.
我认为 indexPath 和 tableView 可能不会被完成块复制,因为它们是在 If-Statement 中使用的。所以我在完成块执行之前保留它们。
代码是:
- (void)downloadImageAtURL:(NSString *)imageURL name:(NSString *)name serial:(BOOL)serial forTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *cachedImagesOfURLs = self.cachedImagesOfURLs;
UITableView *strongTableView = [tableView retain];
NSIndexPath *strongIndexPath = [indexPath retain];
[self.downloadManager downloadImageAtURL:imageURL
identifier:[self identifierForIndexPath:indexPath]
serial:serial
completion:^(UIImage *image) {
if (image) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[cachedImagesOfURLs setObject:image forKey:imageURL];
id cell = [strongTableView cellForRowAtIndexPath:strongIndexPath];
if ([cell respondsToSelector:@selector(didDownloadImage:withName:)]) {
[cell didDownloadImage:image withName:name];
}
}];
}
[strongTableView release];
[strongIndexPath release];
}];
}
但结果是,当完成块执行并尝试创建一个块并在主线程中运行它时,它会崩溃。调试器打印“-[XXX cellForRowAtIndexPath:]: unrecognized selector sent to instance”。我似乎 tableView 和 indexPath 被释放了。
但我不知道为什么,我试图留住他们。有人可以告诉我如何防止这种崩溃发生吗?非常感谢!
【问题讨论】:
-
但是需要保留这个吗?你有没有直接在块中尝试过方法变量?我认为它可以工作
-
块复制它需要的变量。不需要显式保留。只是不要在块内引用 self.downloadManager。
-
你真的应该切换到 ARC!
-
@Till Yep...我真的这么认为。但我必须支持iOS 4.3,而iOS 4.3 SDK 不支持弱属性。当我的部署目标升级到 iOS 5 时,我将使用 ARC...
-
您可以在 iOS4.3 上使用 unsafe_unretained,因此 ARC 完全可以在该操作系统上使用 - 只是没有它的所有功能。
标签: ios multithreading thread-safety objective-c-blocks