У меня есть массив изображений URL.Как я могу получить высоту изображения из этого быстрее? - PullRequest
0 голосов
/ 02 октября 2018

Мне нужно получить размер изображения, чтобы соответственно управлять высотой ячейки коллекции.Я использую код для получения высоты изображения следующим образом:

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 голосов
/ 01 января 2019

dataWithContentsOfURL будет синхронно получать эти изображения (что особенно проблематично, если это не локальные URL-адреса файлов).Вы почти никогда не хотите использовать этот метод, и, конечно, никогда из основной очереди, потому что это заблокирует ваше приложение, и вы рискуете убить ваше приложение процессом watchdog.

Кроме того, поскольку каждый из этих запросов выполняетсясинхронно, вы выполняете эти запросы последовательно (следующий не будет запущен, пока не закончится предыдущий).Это увеличивает проблемы задержки в сети.

Если вам абсолютно необходимо выполнить этот процесс «извлечения всех изображений», вы должны сделать это асинхронно и одновременно.Например, вы можете дать своему методу обработчик завершения, когда все запросы выполнены:

- (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 Ячейки с автоматическими размерами с автоматической компоновкой ) и при получении изображения перезагрузите эту ячейку.

...