2

我正在使用以下代码异步下载图像并将其设置为图像视图。

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);

我知道这些块会自动保留它们引用的所有值,然后释放它们。但是 self 可以在移动到 downloadQueue 然后转移回 callerQueue 之间释放吗?

4

3 回答 3

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
    });

以下是它的执行方式:

  1. downloadQueue 在 self 上添加保留 // +1
  2. downloadQueue 开始执行块 // +1
  3. callerQueue 在 self 上添加保留 // +2
  4. downloadQueue 释放它的保留 // +1
  5. callerQueue 开始执行内部块 // +1
  6. callerQueue 释放它的保留。// +0

所以,在任何时候,self 都会有一个 retainCount。顺便说一句,您甚至可以随时检查保留计数-[NSObject retainCount]

作为旁注,为什么不使用dispatch_get_main_queue()而不是保存 callerQueue。您永远不应该在任何其他线程上执行 UI 操作。如果您的函数是从任何其他线程调用的,这会更安全。

于 2013-04-26T13:03:37.460 回答
0

首先会发生什么:内部块无法从方法中捕获自身,因为在创建内部块时该方法可能早已不复存在。因此,它从外部块捕获自我。这意味着“self”被用作外部块中的变量,这意味着外部块捕获它。如所写,执行内部块时, self 将在那里。

另一方面,您可能不希望这样。您可能不想让该视图保持活动状态,以便将下载的图像存储在那里。在这种情况下,你写

_weak WhatEverType* weakSelf = self; 

在你的方法中,和

WhatEverType* strongSelf = weakSelf;
if (strongSelf != nil)
{
}

在内部块中。结果:那个内部块没有保留“自我”;self 不会仅仅因为它在块中使用而留下。如果它被释放,weakSelf 被设置为 nil,你检查一下。您无需存储图像,而是将其丢弃。但是一旦 strongSelf 被设置为一个非 nil 指针,你就知道它会一直停留在块的末尾。

于 2014-03-27T13:16:05.830 回答
-2

最好不要将 self 留在队列中或阻塞中。使用以下方法使“自我”成为非保留对象:

__unsafe_unretained ViewController *tempController = self;

然后将每个对象称为 tempController.imageView.image 等等。

于 2013-04-25T04:49:05.330 回答