Как увеличить скорость прокрутки в табличном представлении, когда изображения загружаются в каждую ячейку? - PullRequest
3 голосов
/ 05 мая 2009

Проверьте последние строки перед [возврат ячейки] .. После загрузки изображений скорость прокрутки уменьшается .. кажется, что прокрутка застревает

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
    }

    int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
    NSString *itemDescription=[[stories objectAtIndex: storyIndex]
                                                 objectForKey:@"title"];

    CGRect aframe = CGRectMake(80, 30, 250, 40); 
    textLabel = [[UILabel alloc] initWithFrame:aframe];
        textLabel.font = [UIFont boldSystemFontOfSize:14];
    textLabel.numberOfLines=0;
    textLabel.textColor = [UIColor darkTextColor];
    textLabel.backgroundColor = [UIColor whiteColor];
    [cell.contentView addSubview:textLabel];
    textLabel.text=itemDescription;

    CGRect frame = CGRectMake(0, 0, 70,80);
    UIImageView *TopImageView = [[UIImageView alloc] init];
    [cell.contentView addSubview:TopImageView];
    TopImageView.frame=frame;

    m_strImage = [m_imglinkArray objectAtIndex:storyIndex]; 

    TopImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:m_strImage]]];
    TopImageView.image=TopImage;

    return cell;
}

Не могли бы вы, ребята, помочь мне увеличить скорость прокрутки?

Привет

Arun

Ответы [ 4 ]

2 голосов
/ 05 мая 2009

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

iPhone вызывает cellForRowAtIndexPath всякий раз, когда на экране появляется ячейка - если вы прокрутите вниз, все вышеизложенное выгружается и перезагружается при повторной прокрутке вверх. Как уже отмечалось, это можно решить с помощью шаблонов многопоточности - либо ссылки, размещенной на markj.net, и / или с помощью NSThread. Преимущество NSThread в том, что у вас больше гибкости в решении проблем или в загрузке не только данных изображений. (Я бы использовал оба)

Для того, чтобы сделать это эффективно, вам нужно иметь пользовательский UITableViewCell. Это полезно иметь независимо, потому что вы можете сделать так, чтобы ячейка таблицы отвечала за ее содержимое, а не контроллер представления, и вы могли эффективно управлять форматированием ячейки и содержимым. Вот ссылка на отличный пост о UITableCellView: http://blog.atrexis.com/index.cfm/2009/1/6/iPhone--Customize-the-UITableCellView

Когда вы реализуете UITableViewCell, приложите все усилия, чтобы поместить все вызовы addSubView и форматирования в блок «if (cell == nil)», только , если вы не можете поместить их в свой пользовательский initWithFrame. Вы обнаружите, что iPhone складывает каждое добавленное вами подпредставление - оно не очищает старый вид. Вы можете увидеть это на работе, установив все цвета фона на «UIColor clearColor», а затем измените текст между попаданиями - вы увидите стопку текста поверх друг друга. Обычно это не видно, потому что сплошные фоны закрашивают все «старые» подпредставления.

Прежде чем объединить эти два метода, рассмотрим реализацию "модели". У вас есть представление и контроллер, но все ваши данные должны быть в модели. Все URL-адреса изображений, содержимое и т. Д. Должны быть в чем-то вроде NSMutableArray, собственного объекта или, возможно, через SQLite. Если у вас есть модель, вы можете реализовать кэширование изображений. С кэшированием все изображения будут сохраняться между загрузками вашего приложения, что позволит сэкономить батареи, пропускную способность и время.

Я бы: 1. поместите все свои данные в какую-то модель (NSMutableArray, SQLLite, что-то) 2. Реализуйте свой собственный UITableViewCell 3. Убедитесь, что у вас 0 вызовов addSubView, init или alloc внутри активного блока cellForRowAtIndexPath 4. Используйте пример делегирования или NSThread для загрузки всех изображений в фоновом режиме. 5. Добавьте локальное кэширование изображений

В форумах Apple и на форумах Apple есть несколько хороших примеров кэширования изображений.

2 голосов
/ 05 мая 2009

Несущество имеет много хорошей информации. Еще несколько мыслей:

Ты протекаешь как сумасшедший. В каждой ячейке, которую вы создаете, вы теряете 2 UILabels, UIImageView и UIImage.

Как отмечалось ранее, вы не только пропускаете их, они накапливаются в вашем представлении, потому что вы помещаете один поверх другого с помощью addSubview:.

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

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

Несущественно, что вам нужен класс модели для Story.

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @"MyIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        // Here we do all our cell creation
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];

        // Make the label
        CGRect aframe = CGRectMake(80, 30, 250, 40);
        UILabel *textLabel = [[[UILabel alloc] initWithFrame:aframe] autorelease]; // Note the -autorelease so we don't leak

        textLabel.font = [UIFont boldSystemFontOfSize:14];
        textLabel.numberOfLines=0;
        textLabel.textColor = [UIColor darkTextColor];
        textLabel.backgroundColor = [UIColor whiteColor];
        textLabel.tag = DescriptionTag; // A tag so we can find it later (you'll need a constant for this)
        [cell.contentView addSubview:textLabel];

        // And the second label
        aframe = CGRectMake(80, 30, 250, 40);
        textLabel = [[[UILabel alloc] initWithFrame:aframe] autorelease];
        textLabel.font = [UIFont boldSystemFontOfSize:14];
        textLabel.numberOfLines=0;
        textLabel.textColor = [UIColor darkTextColor];
        textLabel.backgroundColor = [UIColor whiteColor];
        textLabel.tag = TitleTag;
        [cell.contentView addSubview:textLabel];

        // The image view
        CGRect frame = CGRectMake(0, 0, 70,80);
        UIImageView *topImageView = [[[UIImageView alloc] init] autorelease];
        topImageView.frame = frame;
        topImageView.tag = TopImageTag;
        [cell.contentView addSubview:topImageView];
    }

    // all the above was cell creation; we do that as seldom as possible.
    // Now we do cell configuration. We want this to be fast.

    UILabel *descriptionLabel = (UILabel*)[cell.contentView viewWithTag:DescriptionTag];
    descriptionLabel.text = itemDescription;

    UILabel *titleLabel = (UILabel*)[cell.contentView viewWithTag:TitleTag];
    titleLabel.text =[[stories objectAtIndex:indexPath.row] objectForKey:@"title"];

    NSString *imageURLString = [m_imglinkArray objectAtIndex:storyIndex]; // You should have a model class called Story, not two arrays.
    UIImage *image = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURLString]]] autorelease]; // This is still way too slow if it's a remote URL 
    UIImageView *imageView = (UIImageView*)[cell.contentView viewWithTag:TopImageTag];
    imageView.image = image;    

    return cell;
}

Я рекомендую вам потратить некоторое время на изучение TableViewSuite , Практическое управление памятью и Рекомендации по кодированию для какао . Некоторое время изучения основ какао также было бы полезно, потому что стиль кодирования здесь указывает на то, что у вас может не быть прочной основы. Хотя это книга для Mac, я все же рекомендую Программирование Какао для Mac OS X . Если вы заинтересованы в использовании этого для изучения iPhone, я собрал учебный план , который может помочь. Я еще не рассмотрел его, но онлайн-курс Стэнфорда CS193P * ​​1027 * выглядит многообещающе.

1 голос
/ 17 февраля 2010

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

Это называется «загрузка ленивых изображений», и я ссылаюсь на руководство по яблоку здесь: Ленивая загрузка изображений в UITableView

0 голосов
/ 05 мая 2009

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

Особенно, если этот URL является ресурсом, который вы загружаете из Интернета, тогда эта пауза велика.

Я бы порекомендовал вам загрузить изображения в фоновом потоке и отображать изображение-заполнитель, пока они не будут извлечены из сети.

Вы можете попробовать решение, указанное в следующем URL-адресе ...

http://www.markj.net/iphone-asynchronous-table-image/

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