繁体   English   中英

iPhone-GCD第一次不起作用

[英]iPhone - GCD doesn't work for the first time

在我的应用程序中,我从URL加载图像:

-(void)loadImages
{
    ...

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

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

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

但是,当我第一次使用imageView打开view controller时, imageView是空的(即使我等待了很长时间),但是当我再次打开此view controller并且出现图像后,一切都很好。

我的错误在哪里? 抱歉,多线程新手:)

编辑 :我也忘了提一下,当我得到它时,我在tableView使用图像:

 cell.imageView.image = image1;

iOS中的UIElement应始终通过主线程进行更新。 您可以做的是:-

   __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];

这可能不是您要找的答案,但这不是建议的加载URL的方法。 您应该使用可用的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];
    }
}];

您需要通知视图该图像需要重绘。 加:

[imageView setNeedsDisplay];

loadImages方法的末尾。

您在这里遇到许多问题:

  1. 您无法在未运行Runloop的线程上启动网络请求。
  2. 您不能从主线程以外的其他线程更新UI。
  3. [NSData dataWithContentsOfURL:imgUrl1]并不是加载外部资源的安全方法,即使在其他线程上(尤其是在主线程上)也是如此。
  4. 每当您分派到另一个线程时,都将面临表单元已被回收并且不再显示您认为是的数据的风​​险。 (它仍然是相同的单元格实例,但是现在正在显示其他行的数据。)

您应该做什么:

  1. 使用主线程上的异步调用启动网络操作。 (如果需要,可以使用另一个线程或队列,但是需要确保它正在运行运行循环。)
  2. 从您的委托消息中,将图像解码分派到另一个线程上。
  3. 图像解码后,分派回主线程进行更新。
  4. 在实际分配图像之前,请检查该单元是否仍在用于您认为的目的。

您可以使用AFNetworking解决前三个问题。 它包装了委托方法,并让您仅提供成功和失败块。 正如我所描述的,AFNetworking的AFImageRequestOperation特别是在队列之间反弹代码。 (它甚至在不同的线程中运行其主要的网络循环,这不是必需的,但是既然做得很好,为什么不呢?)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM