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: