UIView и UITableView, reloadData странная задержка

у меня есть что-то странное с перекраской моего контроллера вида. Контроллер вида содержит UITableView и счетчик.

у меня есть updateFeed функция (запускается IBOutlet), которая приносит счетчик перед моим контроллером зрения и ставит doUpdate функция в NSOperationQueue.

- (void)updateFeed {
    [self showMuar];
    ResourceLoader *loader = [ResourceLoader sharedResourceLoader];
    [loader updateFeed:[self feed] forDelegate:self];
    isReloading = YES;
}
- (id<ResourceToken>)updateFeed:(Feed *)feed forDelegate:(id)delegate {
     return [self queueOperation:[[Operation alloc] initWithObject:feed withSelector:@selector(doUpdate) delegate:delegate]];
}

на doUpdate называет парсер (startParserWithAdd:) функция кто извлекает контент из интернета и форматирует этот контент для UITableView, а затем выполняет [tableView reloadData].

- (NSError *)doUpdate {
    [self startParserWithAddThreaded:NO];
    return nil;
}
- (void)startParserWithAddThreaded:(BOOL)add {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [self startParserWithAdd:add];
    [pool release];
}

... где-то в функции парсера (startParserWithAdd:)

[tableView setDataSource:self];
[tableView reloadData];

после doUpdate сделано без ошибок и благодаря моему классу операций loadingResourceDidFinish выполняется в контроллере моего вида. loadingResourceDidFinish отправить счетчик в фоновом режиме.

- (void)loadingResourceDidFinish:(Feed*)f {
    isReloading = NO;
    [self loadingResourceDidFinishPostAction];
}
- (void)loadingResourceDidFinishPostAction {
        [self hideMuar];
}
- (void)hideMuar {
    [loadingIndicator stopAnimating];
    [self.view sendSubviewToBack:muar];
}

все работает нормально, но счетчик отправляется в фоновом режиме о 4s после loadingResourceDidFinish закончена.

если быть точным, muar-это UIView с непрозрачностью, который содержит счетчик. Я просто хотел абстрагировать сложность в моем первоначальном объяснении !

Я попытался NSLog это, и похоже, что ничего не перекрашено, пока reloadData не будет завершена. Я думаю, это перекраска. проблема в том, что если я включу свой iPhone в ландшафт сразу после окончания loadingResourceDidFinish, все хорошо, прядильщик исчезает.

Я попытался удалить NSAutoreleasePool в парсер функция, но не меняется.


редактировать

Я изменил код, чтобы сделать его менее запутанным. ReloadData UITableView теперь размещено здесь:

- (void)loadingResourceDidFinishPostAction {
    [tableView reloadData];
    [self hideMuar];
    NSLog(@"loadingResourceDidFinishPostAction end");
}

а для отладки :

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"cellForRowAtIndexPath %i", indexPath.row);
        ...

Итак, почему первая ячейка перекрашивается только через 5s после окончания loadingResourceDidFinishPostAction ?

2010-09-02 10:15:35.279 myapp[9632:5b03] loadingResourceDidFinishPostAction end
2010-09-02 10:15:40.208 myapp[9632:5b03] cellForRowAtIndexPath 0
2010-09-02 10:15:40.697 myapp[9632:5b03] cellForRowAtIndexPath 1
2010-09-02 10:15:40.878 myapp[9632:5b03] cellForRowAtIndexPath 2

это то же самое с моим iPhone 3G и iPhone 4 simulator.

2 ответов


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

пройти путь к коду doUpdate и убедитесь, что все вызовы делегата, которые могут привести к обновлению пользовательского интерфейса, выполняются через performSelectorOnMainThread:.


вот мой новый ответ на ваш отредактированный вопрос.

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

1 / Проверьте, правильно ли вы используете идентификатор ячейки по ячейке

2 / Проверьте, делают ли какие-либо другие методы источника данных и делегата тяжелую сетевую работу, как в

* – tableView:cellForRowAtIndexPath:  required method
* – numberOfSectionsInTableView:
* – tableView:numberOfRowsInSection:  required method

или в:

#  – tableView:heightForRowAtIndexPath:
# – tableView:indentationLevelForRowAtIndexPath:
# – tableView:willDisplayCell:forRowAtIndexPath: