iPhone специально нарисован UITableViewCell, как загрузить + вставить изображения из Интернета в ветке? - PullRequest
1 голос
/ 15 ноября 2009

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

Какова правильная структура для этого? Очевидно, мне нужно загрузить изображение в новой теме. Пока у меня есть следующая функция, сидящая в классе ячеек, который запускается в своем собственном потоке:


- (void)loadImage
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    self.img = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: [myProduct objectForKey:@"ImagePath"]]]];
    [self setNeedsDisplay];
    [pool release];
}

Когда я вызываю это из самой функции drawRect (что плохо), тогда это «работает», но это, очевидно, вызывается каждый раз, когда что-то происходит (выбор и т. Д.). Если я добавлю его в функцию инициализации ячеек uiview, то он будет вызван только для первых 8 ячеек, а затем они будут повторно использованы. Другие варианты привели к тому, что изображение не будет «сброшено» при повторном использовании ячейки, поэтому те же 8 изображений повторяются по таблице (хотя другой текст обновляется).

На данный момент я не беспокоюсь о кешировании, но есть ли примеры того, как это сделать, или кто-нибудь может указать мне правильное направление? Спасибо.

Ответы [ 5 ]

2 голосов
/ 15 ноября 2009

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

В cellForRowAtIndexPath: вы должны получить изображение из кэша (ваш объект myProduct, NSArray, что угодно). Если его там нет, вы должны проверить флаг, чтобы увидеть, загружается ли он уже. Если он еще не загружен, вы устанавливаете этот флаг и отсоединяете новый поток (вам следует заглянуть в NSOperation, это поставит в очередь работу и защитит вас от одновременного запуска слишком большого количества потоков).

В вашей теме вы должны загрузить изображение и затем использовать performSelectorOnMainThread:target:waitUntilDone: для вызова метода в главном потоке с изображением. Этот метод может обновить кэш, установить для флага isLoading значение NO и обновить ячейку. Это важно сделать так, потому что Cocoa требует, чтобы весь ваш код обновления пользовательского интерфейса был в основном потоке.

Я надеюсь, что это полезный план того, что делать.

1 голос
/ 16 июля 2010

Это должно ответить на ваш запрос. LazyTableImages

1 голос
/ 16 ноября 2009

Если вы не видели явной документации от Apple о том, что UIImage поточно-ориентирован, я не думаю, что вам следует это делать. Вместо этого получите ваше изображение как NSData и превратите его в UIImage в вашем основном потоке. Основное правило заключается в том, что вся работа UIKit ДОЛЖНА выполняться в вашем основном потоке, иначе поведение не определено.

0 голосов
/ 16 ноября 2009

посмотрите на соответствующие слайды / видео / пример кода из лекций Стэнфорда cs193p ... Прикладная программа для iphone ...

0 голосов
/ 15 ноября 2009

Хорошо, когда вы удаляете ячейку из очереди, вы можете принудительно загрузить изображение туда. Вам не нужно делать это в init ... обычно вы делаете:

cell = dequeueCell...
if (!cell) {
   //create one
}

return cell;

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

...