UIView и UITableView, reloadData странная задержка - PullRequest
9 голосов
/ 01 сентября 2010

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

У меня есть функция updateFeed (запущенная IBOutlet), которая выводит spinner перед моим контроллером представления ипомещает функцию 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 вызывает функцию parser (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 выполнен без ошибок, и благодаря моему классу Operation loadingResourceDidFinish выполняется в моем контроллере представления. loadingResourceDidFinish отправить счетчик в фоновом режиме.

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

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

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

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

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

Я, конечно, что-то не так понял, но я не знаю, что это ...


edit

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

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

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

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

Так почему первая ячейка перекрашивается только через 5 с после окончания загрузки ResourceDidFinishPostAction?

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.

Ответы [ 2 ]

31 голосов
/ 03 сентября 2010

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

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

0 голосов
/ 01 сентября 2010

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

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

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

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

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

или в:

#  – tableView:heightForRowAtIndexPath:
# – tableView:indentationLevelForRowAtIndexPath:
# – tableView:willDisplayCell:forRowAtIndexPath:
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...