iPhone: изображение ячейки повторяется при загрузке с URL - PullRequest
0 голосов
/ 14 мая 2010

Я занимаюсь разработкой демонстрационной программы чтения RSS для iPhone. У меня, очевидно, есть табличное представление для отображения каналов, а затем подробное представление. Некоторые из этих каналов имеют миниатюру, которую я хочу отобразить на cell.imageview таблицы, а некоторые нет.

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

Вот кусок моего кода. Я могу загрузить скриншоты позже

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: @"rssItemCell"];
        if(nil == cell){
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"rssItemCell"]autorelease];
        }
        BlogRss *item = [[[self rssParser]rssItems]objectAtIndex:indexPath.row];
        cell.textLabel.text = [item title];
        cell.detailTextLabel.text = [item description];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        // Thumbnail if exists
        if(noticia.imagePath != nil){
            NSData* imageData;
            @try {
                imageData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:item.imagePath]];
            }
            @catch (NSException * e) {
                //Some error while downloading data
            }
            @finally {
                item.image = [[UIImage alloc] initWithData:imageData];
                [imageData release];
            }
        }

        if(item.image != nil){
            [[cell imageView] setImage:item.image];
        }
        return cell;
    }

Любая помощь будет очень ценится.

Ответы [ 2 ]

2 голосов
/ 14 мая 2010

Легко.

Клетки используются повторно. Просто убедитесь, что вы очищаете cell.imageView.image каждый раз, когда заполняете ячейку. Возможно, вам просто нужно удалить строку if (item.image! = Nil).

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

EDIT

RickiG делает много хороших замечаний: cellForRowAtIndexPath должен отображать данные из модели и как можно меньше!

Идея простого предоставления модели, готовой к просмотру, довольно хороша (я делаю это с ASP.NET MVC), но должна быть сбалансирована с методами минимизации памяти JustInTime в iPhone, и давайте посмотрим правде в глаза, вы не совершаете настоящий грех попытки прочитать данные из элементов управления в вашем табличном представлении - это действительно не работает!

Худшее, что вы делаете, - это чтение веб-данных на cellForRowAtIndexPath, поскольку это заблокирует Великобританию. Вместо этого вы должны отобразить пустое изображение или изображение-заполнитель и вызвать фоновую выборку, которая обновит модель данными, а затем запустить перезагрузку - предпочтительно конкретной ячейки.

1 голос
/ 14 мая 2010

UITableView создан для отражения «модели», поэтому никогда не пытайтесь изменить данные / представления для ячейки самостоятельно после того, как вы ее построите или будете ссылаться на ячейку на основе порядкового номера и т. п., создайте массив ваших данных, я обычно создаю отдельный объект CellViewEntity, который содержит все необходимые мне данные в ячейке как заголовок, подробный текст и т. д., но также и такие вещи, как поведение, он расширен, имеет ли он особый вид и т. д.

Затем я создаю UIView CellView, который заполняется необходимой графикой и методами, например, - (void) shouldDisplayCheckmark: (BOOL) значение и так далее. Я устанавливаю тег объекта CellVIew - [cellView setTag: 15] и освобождаю CellView. Теперь я могу ссылаться на него позже, не сохраняя его, и пусть UITableVIew решит, что следует освободить / сохранить.

cellForRowAtIndexPath постоянно вызывается SDK при прокрутке при обновлении, когда ячейка входит или выходит из экрана. Так что не вкладывайте в эту функцию тяжелые экземпляры, веб-вызовы и т. Д.

В этом блоке if.

   if(nil == cell){
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"rssItemCell"]autorelease];
        }

Я создаю экземпляр ячейки и CellView и добавляю объект CellView к представлению ячейки. (с тегом)

вне if (cell == nil) Я обновляю CellVIew только данными из массива модели.

Это означает, что если ячейка существует, она будет использоваться повторно, и ее свойства будут обновлены из массива, если она не создана и не присоединена к ячейке. Вне оператора if я ссылаюсь на свой CellView следующим образом:

[(CellView*)[cell viewWithTag:15] updateValuesAccordingToModelArray:[array objectAtIndes:indexPath.row]]; //this will be the only code executed for a already existing cell.

Полагаю, это может показаться немного превышающим лимит, но вы не можете ссылаться на ячейки, подобные этой [uitableView cellAtRow: 14], согласованным образом, потому что UITableView кэширует ячейку, которая находится за пределами экрана, и соответственно изменяет indexPath. Такой подход вы можете сделать со своим массивом.

Теперь перестанет бродить :) ... отделить все данные в удобном пакете, поддерживающем tableView, и передать их в представление таблицы - только в одну сторону.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...