iphone – iOS 4 GCD问题

我查看了WWDC 2010中的一些演示文稿,并阅读了大部分有关块和并发性的文档,并且在Grand Central Dispatch中使用带有串行队列的块有几个问题.
我有一个iOS 4项目,它有一个scrollview和一个图像信息字典 – 图像的URL等等.我想使用GCD和块来下载图像并将它们放在我的scrollview中,从而不会阻塞主线程.我写了下面似乎有用的代码:

for (NSDictionary* dict in images)
{
     dispatch_async(image_queue, ^{

           NSString* urlString = [dict objectForKey:@"url"];
           NSURL* url = [NSURL URLWithString:urlString];
           NSData* imageData = [[NSData alloc] initWithContentsOfURL:url];
           UIImage* image = [UIImage imageWithData:imageData];
           UIImageView* imageView = // initialize imageView with image;      

           dispatch_async(dispatch_get_main_queue(), ^{
                [self.scrollView addSubview:imageView];
           });
           [imageData release];
      });
}

我有两个问题:

>根据并发指南,我不应该从非标量类型的封闭范围中捕获变量 – 在我的代码中我捕获了dict,它是一个NSDictionary *对象.如果我不被允许捕获它,我该如何编写代码呢?块只捕获实际使用的封闭范围中的变量吗?
>如果在通过串行调度队列获取所有图像之前离开当前的ViewController会发生什么?我不认为他们知道创建它们的ViewController已经消失所以当他们执行完成处理程序时会发生什么,我将图像视图插入主线程的scrollview?它会导致错误或什么?当我的ViewController消失时,如何取消串行队列上的任何剩余操作?

最好的祝福,

最佳答案
>虽然这是一个琐碎的问题,但这对于理解并发指南试图告诉您的内容非常重要:指针是标量类型.因此,您可以捕获所有想要的块内的指针……但是您必须认识到它们指向的内存的生命周期! NSDictionary *是一种id,当你在一个块中引用一个id时,运行时负责保留id(如果块被复制(通过dispatch_async()),然后在块时释放它本身被解除分配.是的,一个块只捕获其中引用的变量.
>既然您现在知道异步块已经自我保留,那么应该清楚(呃)(模数内存管理错误)您的ViewController在块完成之前不能“消失”.所以它不会崩溃 – 但是你应该注意到你真的想要一种方法来取消这种异步工作,而你实际上还没有计划再使用这些结果了.一个简单但有效的模式是在异步块的开头放置一个测试,检查是否仍然要完成工作.

转载注明原文:iphone – iOS 4 GCD问题 - 代码日志