我使用以下代码异步下载图像并将其设置为图像视图。
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("com.myapp.processsmagequeue", NULL);
dispatch_async(downloadQueue, ^{
NSData * imageData = [NSData dataWithContentsOfURL:url];
dispatch_async(callerQueue, ^{
self.imageView.image = [UIImage imageWithData:imageData];
[self.imageActivityIndicatorView setHidden:YES];
[self.imageView setHidden:NO];
});
});
dispatch_release(downloadQueue);
我知道这些块会自动保留它们引用的所有值,然后释放它们。但是,在移动到downloadQueue然后转回callerQueue之间可以自我释放吗?
答案 0 :(得分:1)
这应该没问题。
dispatch_async(downloadQueue, ^{ // --> downloadQueue will add a retain on self when it's created
dispatch_async(callerQueue, ^{ // --> callerQueue will add a retain on self when it's created
...
}); // --> callerQueue will release it's retain when it gets dealloced just after returning from here
// --> downloadQueue will release it's retain when it gets dealloced just after returning from here
});
以下是它的执行方式:
因此,在任何时候,都会有自己的retainCount。顺便说一句,您甚至可以随时查看保留计数-[NSObject retainCount]
。
作为旁注,为什么不使用dispatch_get_main_queue()
而不是保存callerQueue。您应该从不在任何其他线程上执行UI操作。如果从任何其他线程调用函数,这样更安全。
答案 1 :(得分:0)
首先会发生什么:内部块无法从方法中捕获self,因为在创建内部块时该方法可能会很久。因此,它从外部块捕获自我。这意味着“self”用作外部块中的变量,这意味着外部块捕获它。因此,当执行内部块时,self将存在。
另一方面,你可能不希望这样。您可能不希望保持该视图处于活动状态,以便下载的图像可以存储在那里。在那种情况下,你写
_weak WhatEverType* weakSelf = self;
在您的方法中,
WhatEverType* strongSelf = weakSelf;
if (strongSelf != nil)
{
}
在内部块中。结果:内部块不保持“自我”保留;自我不会因为它被用在街区而留在身边。如果它被dealloc'ed,weakSelf设置为nil,你检查一下。你可以把它扔掉,而不是存储图像。但是一旦strongSelf被设置为非零指针,你就知道它会一直停留在块的末尾。
答案 2 :(得分:-2)
最好不要将自己保留在队列中或阻止。使用以下命令使“self”成为非保留对象:
__unsafe_unretained ViewController *tempController = self;
然后将每个对象调用为tempController.imageView.image,依此类推。