Что лучший подход к асинхронному изображению, кэширующемуся на iPhone?

Я создаю приложение для iPhone, которое раскроет данные из сети API, включая адреса электронной почты. Я хотел бы отобразить изображение, связанное с каждым адресом электронной почты в ячейках таблицы, таким образом, я ищу Адресную книгу изображения и возвращаюсь к значению по умолчанию, если адрес электронной почты не находится в книге. Это работает отлично, но у меня есть несколько проблем:

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

  • Ячейки таблицы: Таким образом, я думал, что соберу все адреса электронной почты, для которых я должен найти изображения и найти их внезапно. Таким образом, я выполняю итерации через книгу только однажды для всех адресов. Но это не работает хорошо на ячейки таблицы, где каждая ячейка соответствует единственному адресу электронной почты. Я должен был бы или собрать все изображения прежде, чем отобразить любые ячейки (потенциально медленный) или иметь каждую ячейку, ищут каждое изображение, поскольку это загружается (еще медленнее, поскольку я должен был бы выполнить итерации через книгу для нахождения достойным каждого адреса электронной почты).

  • Асинхронный Поиск: Таким образом я думал, что буду искать их оптом, но асинхронно, с помощью NSInvocationOperation. Для каждого изображения, найденного в AddressBook, я сохранил бы миниатюру в тестовой среде приложения. Затем каждая ячейка могла просто сослаться на этот файл и показать значение по умолчанию, если это не существует (потому что это не находится в книге или еще не было найдено). Если изображение позже найдено в асинхронном поиске, в следующий раз, когда изображение должно быть отображено, это внезапно появилось бы. Это могло бы работать хорошо на периодическую регенерацию изображений (для того, когда изображения были изменены в адресной книге, например). Но затем для любого приведенного примера моего приложения, изображение не может на самом деле обнаружиться некоторое время.

  • Асинхронный Поиск Ячейки таблицы: Идеально, я использовал бы что-то как асинхронное обновление ячейки таблицы markjnet для обновления ячеек таблицы с изображением, после того как оно было загружено. Но чтобы это работало, я должен был бы вылететь NSInvocationOperation задание для каждой ячейки, поскольку это отображено и если кэшируемый значок отсутствует в песочнице. Но затем мы вернулись к неэффективной итерации через всю адресную книгу для каждого — и это может быть большим количеством из них, если Вы только что загрузили целый набор новых адресов электронной почты.

Таким образом, мой вопрос: Как другие делают это? Я играл с Tweetie2, и похоже, что это обновляет отображенные ячейки таблицы асинхронно. Я предполагаю, что это отправляет отдельный Запрос HTTP за каждым изображением, в котором это нуждается. Если так, я предполагаю, что поиск локальной адресной книги по электронной почте обращается разве, кто-либо не менее эффективен, поэтому возможно, это - лучший подход? Просто не волнуются о проблемах производительности, связанных с поиском адресной книги?

Если так, действительно ли сохранение является изображением миниатюр в песочнице лучший подход к кэшированию? И если я хотел создать новое задание для обновления всех миниатюр с какими-либо изменениями в адресной книге, говорят один раз в день, что лучший подход к выполнению так?

Как делают остальная часть Вас решает этот вид проблемы? Предложения очень ценились бы!

10
задан Community 23 May 2017 в 11:45
поделиться

3 ответа

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

Создайте NSMutableDictionary, который будет служить вашим кешем в памяти для результатов поиска. Инициализируйте этот словарь, используя каждый адрес электронной почты из загрузки в качестве ключа, а в качестве значения ключа укажите дозорный (например, [NSNull null] ).

Затем переберите каждый ABRecordRef в адресной книге, вызывая ABRecordCopyValue (record, kABPersonEmailProperty) и просматривая результаты в каждом возвращаемом ABMultiValue. Если какой-либо из адресов электронной почты является ключами в вашем кэше, установите [NSNumber numberWithInt: ABRecordGetRecordId (record)] в качестве значения этого ключа в вашем словаре.

Используя этот словарь в качестве поискового индекса, вы можете быстро получить изображения ABRecordRefs только для адресов электронной почты, которые вы в данный момент отображаете в табличном представлении с учетом текущей позиции прокрутки пользователя, как это предлагается в ответе hoopjones.Вы можете добавить прослушиватель изменений адресной книги, чтобы сделать ваш кеш недействительным, запустить другую операцию индексирования, а затем обновить представление, если вашему приложению требуется такой уровень «актуальности».

2
ответ дан 4 December 2019 в 03:38
поделиться

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

Что-то вроде этого (это немного изменено из учебника, который я нашел в Интернете, но сейчас не могу найти, извиняюсь за то, что не цитирую автора):

- (void)loadContentForVisibleCells
{
    NSArray *cells = [self.table visibleCells];
    [cells retain];
    for (int i = 0; i < [cells count]; i++) 
    { 
        // Go through each cell in the array and call its loadContent method if it responds to it.
        AddressRecordTableCell *addressTableCell = (AddressRecordTableCell *)[[cells objectAtIndex: i] retain];
        [addressTableCell loadImage];
        [addressTableCell release];
        addressTableCell = nil;
    }
    [cells release];
}


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 
{
    // Method is called when the decelerating comes to a stop.
    // Pass visible cells to the cell loading function. If possible change 
    // scrollView to a pointer to your table cell to avoid compiler warnings
    [self loadContentForVisibleCells]; 
}


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
    if (!decelerate) 
    {
       [self loadContentForVisibleCells]; 
    }
}

Как только вы узнаете, какие записи адресов видны в данный момент, просто выполните их поиск (вероятно, 5-7 записей) будет молниеносным. После того, как вы захватите изображение, просто кешируйте его в словаре, чтобы вам не приходилось повторять запрос изображения позже.

2
ответ дан 4 December 2019 в 03:38
поделиться

Похоже, вы пытаетесь реализовать отложенную загрузку изображений в UITableView. есть хороший пример от Apple, я ссылаюсь на него здесь: Ленивая загрузка изображений в UITableView

1
ответ дан 4 December 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: