iPhone - GCD第一次不起作用

时间:2013-04-01 17:03:44

标签: iphone ios objective-c xcode cocoa

在我的应用中,我从网址加载图片:

-(void)loadImages
{
    ...

    image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:imgUrl1]];
}

为了避免在下载完成之前阻塞主线程,我将调用此方法 -viewDidAppear 使用GCD

dispatch_async( dispatch_get_global_queue(0,0), ^{
            [self loadImages];
        });

但是,当我第一次使用view controller打开imageView时,imageView为空(即使我等了很长时间),但在我打开之后{ {1}}再次显示图像,一切都很好。

我的错误在哪里? 对不起,刚接触多线程:)

修改: 我也忘了提到,当我得到它时,我会使用view controller中的图像:

tableView

5 个答案:

答案 0 :(得分:2)

iOS中的UIElements应始终通过主线程更新。 你能做的是: -

   __block NSData *data;
    dispatch_queue_t myQueue = dispatch_queue_create("com.appName", NULL);
    dispatch_async(myQueue, ^{
       data = [NSData dataWithContentsOfURL:imgUrl1];
       dispatch_async(dispatch_get_main_queue(), ^(void) {
       cell.imageView.image = [UIImage imageWithData = data];
    });
    });

或者你还有一种更好的方法是使用AFNetworking从URL获取图像。它更快更容易。 你只需编写一行代码: -

[cell.imageView setImageWithURL:imgUrl1];

答案 1 :(得分:2)

这可能不是您正在寻找的答案,但这不是加载网址的推荐方式。您应该使用可用的URL加载类,例如NSURLRequest和NSURLConnection。

试试这个:

NSURLRequest *imageRequest = [[NSURLRequest alloc] initWithURL:imageURL];
[NSURLConnection sendAsynchronousRequest:imageRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (!error) {
        UIImage *image = [[UIImage alloc] initWithData:data];
        [imageView setImage:image];
    }
}];

答案 2 :(得分:1)

您需要通知视图需要重新绘制图像。添加:

[imageView setNeedsDisplay];

loadImages方法的结尾。

答案 3 :(得分:1)

这里有很多问题:

  1. 您无法在未运行runloop的线程上启动网络请求。
  2. 您无法从主线程以外的线程更新UI。
  3. [NSData dataWithContentsOfURL:imgUrl1]不是加载外部资源的安全方法,即使在不同的线程上(尤其是在主线程上)。
  4. 每当您发送到其他线程时,您都会面临表格单元格已被回收并且不再显示您认为的数据的风​​险。 (它仍然是相同的单元格实例,但现在显示其他行的数据。)
  5. 你应该做什么:

    1. 使用主线程上的异步调用启动网络操作。 (如果需要,您可以使用另一个线程或队列,但是您需要确保它正在运行runloop。)
    2. 从您的委托消息中,在不同的线程上发送图像解码。
    3. 解码图像后,发送回主线程进行更新。
    4. 在实际分配图像之前,请检查单元格是否仍在用于您认为的目的。
    5. 您可以使用AFNetworking解决前三个问题。它包装委托方法,让您只提供成功和失败块。正如我所描述的,AFNetworking的AFImageRequestOperation特别会在队列之间反弹代码。 (它甚至在不同的线程中运行其主要的网络循环,这不是必要的但是因为它做得好,为什么不呢?)

      您仍然需要验证单元格的身份。

答案 4 :(得分:0)

由于您在TableView中使用它,添加[self.tableView reloadData];在loadImages方法的最后。