Я создаю приложение для iPhone, которое раскроет данные из сети API, включая адреса электронной почты. Я хотел бы отобразить изображение, связанное с каждым адресом электронной почты в ячейках таблицы, таким образом, я ищу Адресную книгу изображения и возвращаюсь к значению по умолчанию, если адрес электронной почты не находится в книге. Это работает отлично, но у меня есть несколько проблем:
Производительность: рецепты, которые я нашел для поиска записи адресной книги по электронной почте, обращаются (или номер телефона) являются по сообщениям довольно медленными. Причина этого состоит в том, что нужно выполнить итерации по каждой записи адресной книги, и для каждого, который имеет изображение, выполните итерации по всем адресам электронной почты для нахождения соответствия. Это может быть трудоемким для большой адресной книги, конечно.
Ячейки таблицы: Таким образом, я думал, что соберу все адреса электронной почты, для которых я должен найти изображения и найти их внезапно. Таким образом, я выполняю итерации через книгу только однажды для всех адресов. Но это не работает хорошо на ячейки таблицы, где каждая ячейка соответствует единственному адресу электронной почты. Я должен был бы или собрать все изображения прежде, чем отобразить любые ячейки (потенциально медленный) или иметь каждую ячейку, ищут каждое изображение, поскольку это загружается (еще медленнее, поскольку я должен был бы выполнить итерации через книгу для нахождения достойным каждого адреса электронной почты).
Асинхронный Поиск: Таким образом я думал, что буду искать их оптом, но асинхронно, с помощью NSInvocationOperation
. Для каждого изображения, найденного в AddressBook, я сохранил бы миниатюру в тестовой среде приложения. Затем каждая ячейка могла просто сослаться на этот файл и показать значение по умолчанию, если это не существует (потому что это не находится в книге или еще не было найдено). Если изображение позже найдено в асинхронном поиске, в следующий раз, когда изображение должно быть отображено, это внезапно появилось бы. Это могло бы работать хорошо на периодическую регенерацию изображений (для того, когда изображения были изменены в адресной книге, например). Но затем для любого приведенного примера моего приложения, изображение не может на самом деле обнаружиться некоторое время.
Асинхронный Поиск Ячейки таблицы: Идеально, я использовал бы что-то как асинхронное обновление ячейки таблицы markjnet для обновления ячеек таблицы с изображением, после того как оно было загружено. Но чтобы это работало, я должен был бы вылететь NSInvocationOperation
задание для каждой ячейки, поскольку это отображено и если кэшируемый значок отсутствует в песочнице. Но затем мы вернулись к неэффективной итерации через всю адресную книгу для каждого — и это может быть большим количеством из них, если Вы только что загрузили целый набор новых адресов электронной почты.
Таким образом, мой вопрос: Как другие делают это? Я играл с Tweetie2, и похоже, что это обновляет отображенные ячейки таблицы асинхронно. Я предполагаю, что это отправляет отдельный Запрос HTTP за каждым изображением, в котором это нуждается. Если так, я предполагаю, что поиск локальной адресной книги по электронной почте обращается разве, кто-либо не менее эффективен, поэтому возможно, это - лучший подход? Просто не волнуются о проблемах производительности, связанных с поиском адресной книги?
Если так, действительно ли сохранение является изображением миниатюр в песочнице лучший подход к кэшированию? И если я хотел создать новое задание для обновления всех миниатюр с какими-либо изменениями в адресной книге, говорят один раз в день, что лучший подход к выполнению так?
Как делают остальная часть Вас решает этот вид проблемы? Предложения очень ценились бы!
Независимо от того, какую стратегию вы используете для фактического кэширования изображений, я бы по возможности делал только один проход через данные адресной книги каждый раз, когда вы получаете пакет адресов электронной почты. (И да, я бы сделал это асинхронно.)
Создайте NSMutableDictionary, который будет служить вашим кешем в памяти для результатов поиска. Инициализируйте этот словарь, используя каждый адрес электронной почты из загрузки в качестве ключа, а в качестве значения ключа укажите дозорный (например, [NSNull null]
).
Затем переберите каждый ABRecordRef в адресной книге, вызывая ABRecordCopyValue (record, kABPersonEmailProperty)
и просматривая результаты в каждом возвращаемом ABMultiValue. Если какой-либо из адресов электронной почты является ключами в вашем кэше, установите [NSNumber numberWithInt: ABRecordGetRecordId (record)]
в качестве значения этого ключа в вашем словаре.
Используя этот словарь в качестве поискового индекса, вы можете быстро получить изображения ABRecordRefs только для адресов электронной почты, которые вы в данный момент отображаете в табличном представлении с учетом текущей позиции прокрутки пользователя, как это предлагается в ответе hoopjones.Вы можете добавить прослушиватель изменений адресной книги, чтобы сделать ваш кеш недействительным, запустить другую операцию индексирования, а затем обновить представление, если вашему приложению требуется такой уровень «актуальности».
Я бы использовал последний из перечисленных вами методов (асинхронный поиск ячеек таблицы), но просматривал изображения только для текущих отображаемых записей. Я перегружаю методы 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 записей) будет молниеносным. После того, как вы захватите изображение, просто кешируйте его в словаре, чтобы вам не приходилось повторять запрос изображения позже.
Похоже, вы пытаетесь реализовать отложенную загрузку изображений в UITableView. есть хороший пример от Apple, я ссылаюсь на него здесь: Ленивая загрузка изображений в UITableView