【问题标题】:loading images from a background thread using blocks使用块从后台线程加载图像
【发布时间】:2011-11-22 01:23:00
【问题描述】:

我有以下方法,它基本上调用了一个请求,在后台线程中加载图像的 NSData 数组:

[query findObjectsInBackgroundWithBlock:^(NSArray * objects, NSError * error){

}];

在这种情况下,objects 是 NSData 的数组。问题是,如果我要加载 100 个图像(数组中有 100 个元素)。这意味着用户将不得不等待相当长的时间才能看到 UITableView 中显示的任何图像。我想要做的是让他们在图像可用/加载后看到它。我是否必须更改代码以便它执行 100 个后台线程来加载图像?

【问题讨论】:

  • 尝试干预代码,一旦后台线程显示它有图像,开始显示它。就像我视频游戏在更新方法中加载内容一样。

标签: iphone objective-c ipad


【解决方案1】:

不,您不必创建那么多后台线程。使用NSOperationQueue

【讨论】:

    【解决方案2】:

    您可以创建NSInvocationOperation并将其设置为NSOperationQueue

    例如: 初始化NSOperationQueue

    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
    

    创建后NSInvocationOperation:

    NSInvocationOperation* downloadOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(selectorToDownloadImage:) object:YouData];    
    [operationQueue addOperation:downloadOperation];
    [downloadOperation release]; 
    

    【讨论】:

    • 你为什么不在你的答案中编辑它并让它看起来不错?
    【解决方案3】:

    你可以在你的 cellForRowAtIndexPath 中实现类似的东西:

    这样你在后台加载每个图像,一旦加载,相应的单元格就会在 mainThread 上更新。

          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
            NSData *data0 = [NSData dataWithContentsOfURL:someURL];
            UIImage *image = [UIImage imageWithData:data0];
    
            dispatch_sync(dispatch_get_main_queue(), ^(void) {
                UIImageView* imageView = (UIImageView*)[cell viewWithTag:100];
                imageView.image = image;
            });
        });
    

    【讨论】:

    • 严格来说,UIKit(UIImage 是其中的一部分)不是后台线程安全的,但您似乎可以在这里摆脱它,因为您只使用 'UIImage图像与数据'。不错的技巧!
    • 这是一个旧答案,但由于最近有 cmets 引用它,我想添加此警告:此解决方案可能无法与表格视图中的单元格更新一起正常工作,并且使用dataWithContentsOfURL: 进行远程访问,这不可靠且不适合该目的。
    • 嘿。谢谢你的评论。我知道在 GCD 中使用这种方法可能不是纯粹的优雅,但由于我在实践中从未遇到任何问题,我会对你在其中看到的问题感兴趣?
    • 要下载远程资源,最好使用NSURLConnection。方法族“xxxWithContentOfURL:”实际上是从文件 URL 加载的。然后,每个严肃的应用程序都需要取消一个正在运行的请求。要么这是您希望在她认为合适时取消连接的用户。是您,因为在您的代码中,当用户从视图切换并且结果不再使用时,您经常必须取消正在运行的请求。后者还可以防止意外升级启动请求,这可能会占用 CPU 并消耗内存。
    • 注意:当你必须取消一个请求时,你需要一个NSURLConnection 实例来发送cancel 消息。这也意味着您必须异步模式下使用NSURLConnection并实现委托。
    猜你喜欢
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    相关资源
    最近更新 更多