我有一个图片网址数组。如何以更快的方式从中获取图像高度?

时间:2018-10-02 06:40:10

标签: uicollectionview objective-c-blocks uicollectionviewlayout waterfall

我需要获取图像大小,以便据此管理收集单元的高度。我使用代码获取图像高度如下:

for (NSURL*image1 in imageurlArray)
        {
            NSData *imageData = [NSData dataWithContentsOfURL:image1];
            UIImage *img = [UIImage imageWithData:imageData];
                CGSize finalsize;
                finalsize.height = 15+img.size.height+15+30+40;
                [_cellHeights addObject:@(finalsize.height)];
        }

但是,如果我使用它,将需要5到7秒钟才能完成收集视图中的加载(瀑布模式)。

1 个答案:

答案 0 :(得分:0)

dataWithContentsOfURL将同步检索那些图像(如果这些图像不是本地文件URL,则尤其有问题)。您几乎永远不会使用此方法,当然也永远不会从主队列中使用该方法,因为它会阻止您的应用程序,并且您有可能被监视程序杀死您的应用程序。

此外,由于每个请求都是同步执行的,因此您将依次执行这些请求(直到前一个请求完成后,它才开始下一个请求)。这会放大网络延迟问题。

如果绝对必须执行此“获取所有图像”过程,则应异步并发进行。例如。您可以在所有请求完成后为您的方法提供完成处理程序:

- (void)fetchImageSizesWithCompletion:(void (^_Nonnull)(void))completion {
    dispatch_group_t group = dispatch_group_create();

    for (NSURL *url in imageurlArray) {
        dispatch_group_enter(group);
        NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (data != nil) {
                UIImage *image = [UIImage imageWithData:data];

                // do something with image.size

                // note, if updating UI, you should dispatch that back to the main queue, e.g.
                //
                // dispatch_async(dispatch_get_main_queue(), ^{
                //     // update UI here
                // });
            }
            dispatch_group_leave(group);
        }];
        [task resume];
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // do something when they're all done, e.g. call this methods completion handler
        completion();
    })
}

可能更好,您不应该尝试预先加载图像,而是让单元在需要它们时请求它们各自的图像。并使用自动调整大小的单元格(请参见UICollectionView Self Sizing Cells with Auto Layout),并在检索到图像后重新加载该单元格。