reloadRowsAtIndexPaths прекращает загрузку UITableViewCells? - PullRequest
0 голосов
/ 01 июня 2011

Я пытаюсь включить значки в UITableView. Таблица в основном выбирает веб-сайты, и я хочу отобразить значок справа. Сначала я поместил значок заполнителя справа и позволил функции в фоновом режиме работать. Эта функция берет URL-адрес веб-сайта, анализирует его и пытается найти значок. Если это не может найти это, это сохраняет то же самое изображение заполнителя; в противном случае он заменяет его на значок сайта. Сначала я попытался использовать [tableView reloadData], который хорошо работал в симуляторе, но он делал действительно странные и ненадежные вещи (например, он создавал несколько ячеек, но затем оставлял гигантскую пустую ячейку). Во всяком случае, я наткнулся на reloadRowsAtIndexPaths, и похоже, что мне нужно использовать функцию. Тем не менее, результаты все еще довольно ненадежны. У меня есть функция извлечения, работающая в фоновом режиме как таковая:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...//other code here for showing website labels

    //obtain the favicon.ico
if(!this_article.iconLoaded){
    this_article.iconLoaded = TRUE;
    NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:this_article, @"article", indexPath, @"indexPath", nil];
    [self performSelectorInBackground:@selector(fetchFaviconWrapper:) withObject:args];
}

cell.favicon.image = this_article.icon;

return cell;
}

в FetchFaviconWrapper:

- (void)fetchFaviconWrapper:(NSDictionary *)args {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self fetchFavicon:[args objectForKey:@"article"]];
NSArray *paths = [NSArray arrayWithObject:[args objectForKey:@"indexPath"]];
[articleTable beginUpdates];
[articleTable reloadRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[articleTable endUpdates];
[pool release];
}

По сути, fetchFavicon берет веб-сайт, принимает URL-адрес хоста, добавляет "/favicon.ico", создает его в объект NSData и находит изображение (если оно существует). Тем не менее, это также было довольно ненадежным. Что было бы лучшим способом заменить изображение заполнителя при запуске потока в фоновом режиме? Я мог делать все в главном потоке, но это просто заставляет таблицу загружаться медленно. Кажется, я что-то упускаю из виду или что-то, что просто забыл добавить ... просто не могу понять.

Ответы [ 3 ]

2 голосов
/ 01 июня 2011

Не совсем ясно, осуществляете ли вы доступ и изменяете свой пользовательский интерфейс из отдельного потока.

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

Существует обходной путь, если вы хотите сохранить свой второй поток.Действительно, вы можете отправлять сообщения в ваш объект пользовательского интерфейса, используя:

-performSelectorOnMainThread:withObject:waitUntilDone:

вместо отправки их непосредственно из вторичного потока.

Если этот обходной путь не решит проблему для вас, тогда япредложил бы изменить дизайн вашего приложения так, чтобы вторичный поток имел доступ только к вашей модели, не обращаясь к пользовательскому интерфейсу.Все операции, которые изменяют пользовательский интерфейс, должны выполняться в главном потоке.Если вам нужно вызвать reloadData на вашем столе, когда модель будет готова, вы можете сделать это, используя performSelectorOnMainThread:withObject:waitUntilDone.

0 голосов
/ 01 июня 2011

Я определенно повторяю нет пользовательского интерфейса из фонового потока .

измените ваш исходный код:

- (void)fetchFaviconWrapper:(NSDictionary *)args {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  [self fetchFavicon:[args objectForKey:@"article"]];
  NSArray *paths = [NSArray arrayWithObject:[args objectForKey:@"indexPath"]];

  [articleTable beginUpdates];
  [articleTable reloadRowsAtIndexPaths:paths 
                      withRowAnimation:UITableViewRowAnimationFade];
  [articleTable endUpdates];

  [pool release];
}

на это, и посмотрите, если у вас все еще естьпроблема

- (void)fetchFaviconWrapper:(NSDictionary *)args {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  [self fetchFavicon:[args objectForKey:@"article"]];
  NSArray *paths = [NSArray arrayWithObject:[args objectForKey:@"indexPath"]];

  [self performSelectorOnMainThread:@selector(reloadData) 
                         withObject:nil 
                      waitUntilDone:YES];

  [pool release];
}

В этом случае waitUntilDone не имеет значения, и предпочтительной формой будет сказать ДА.

Другая проблема, которую следует подозревать, если у вас есть поведение в стиле фанк в ячейке, это если вы правильно обрабатываете ячейку.повторное использование.Вы не показали нам этот код, поэтому мы не можем сказать.Если вы где-то сохраняете ссылку на ячейку и вводите в нее данные изображения - вы будете изматывать себя, когда таблица повторно использует ячейку из-под вас.(Я не думаю, что это проблема в этом случае.)

0 голосов
/ 01 июня 2011

Я бы предложил несколько вещей.

  1. Добавление ./favicon.ico не всегда точно.Изучите различные способы добавления значков на сайты для их поддержки.

  2. Что касается замены заполнителя по умолчанию, я предлагаю использовать NSNotificationCenter, чтобы сообщить основной ветке, когда вносить изменения..

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