Отложенный рендеринг UIImageView в UITableView - PullRequest
27 голосов
/ 01 декабря 2009

Хорошо, у меня есть UITableView с пользовательскими UITableViewCell с, каждый из которых содержит UIImageView, изображения которого загружаются асинхронно через NSURLConnection. Все довольно стандартные вещи ...

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

Как заставить таблицу отображать содержимое, даже когда она движется? Спасибо.

- ОБНОВЛЕНИЕ -

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

Ответы [ 4 ]

65 голосов
/ 03 января 2010

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

Вот как можно запланировать соединение в «обычных» режимах, включая UITrackingRunLoopMode:

NSURLRequest *request = ...
NSURLConnection *connection = [[NSURLConnection alloc]
                               initWithRequest:request
                               delegate:self
                               startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
            forMode:NSRunLoopCommonModes];
[connection start];

Обратите внимание, что вы должны указать startImmediately:NO в инициализаторе, который, кажется, идет вразрез с документацией Apple, предлагающей изменить режим цикла выполнения даже после его запуска.

1 голос
/ 07 декабря 2009

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

Еще одним преимуществом NSOperation является то, что вы можете отменить операцию, когда ячейка скользит за пределами экрана. Он будет гораздо более отзывчивым для пользователя, особенно если он быстро прокрутит длинный список. Технический разговор Apple в этом году поддержал эту технику.

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

1 голос
/ 01 декабря 2009

Вы должны прочитать о NSRunLoop. Я подозреваю, что во время прокрутки цикл выполнения выполняется в NSEventTrackingRunLoopMode, и NSURLConnection не включается в этот режим. Возможно, вы могли бы обойти это, вызвав NSInLConnection scheduleInRunLoop: forMode:, чтобы загрузка могла происходить во время прокрутки.

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

0 голосов
/ 03 декабря 2009

Во-первых ... ваше соединение, вероятно, даже не запускается, пока не доберется до mainRunLoop, и здесь также обрабатывается анимация прокрутки.

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

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:wrapper.request delegate:wrapper];

    [connection start];

В процедуре завершения, где вы получаете изображение и устанавливаете cell.imageView.image для полученного изображения, вы должны проверить, принадлежит ли эта ячейка одной из ячеек, отображаемых в данный момент в таблице ... и если поэтому вызовите [tableView reloadData].

    NSInteger itemIndex = theIndexInTheRowDataOfTheCellYouStuffedTheImage

    NSArray *indicies = [_tableView indexPathsForVisibleRows];
    NSUInteger rows = indicies.count;

    if (rows > 0 &&
        itemIndex >= ((NSIndexPath *)[indicies objectAtIndex:0]).row &&
        itemIndex <= ((NSIndexPath *)[indicies objectAtIndex:rows - 1]).row)
    {       
        [_tableView reloadData];
    }
...