Данные не загружаются в UITableView до тех пор, пока я не прокручу
Я пытаюсь загрузить анализируемые данные в ячейки, но проблема в том, что это происходит синхронно, а UitableView не отображается, пока данные не закончили загрузку. Я попытался решить проблему с помощью функции performSelectorInBackground, но теперь данные не загружаются в ячейки до начала прокрутки. Вот мой код:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self performSelectorInBackground:@selector(fethchData) withObject:nil];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
self.listData = nil;
self.plot=nil;
}
-(void) fethchData
{
NSError *error = nil;
NSURL *url=[[NSURL alloc] initWithString:@"http://www.website.com/"];
NSString *strin=[[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
HTMLParser *parser = [[HTMLParser alloc] initWithString:strin error:&error];
if (error) {
NSLog(@"Error: %@", error);
return;
}
listData =[[NSMutableArray alloc] init];
plot=[[NSMutableArray alloc] init];
HTMLNode *bodyNode = [parser body];
NSArray *contentNodes = [bodyNode findChildTags:@"p"];
for (HTMLNode *inputNode in contentNodes) {
[plot addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
NSArray *divNodes = [bodyNode findChildTags:@"h2"];
for (HTMLNode *inputNode in divNodes) {
[listData addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
//here you check for PreCreated cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
//Fill the cells...
cell.textLabel.text = [listData objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
cell.textLabel.numberOfLines=6;
cell.textLabel.textColor=[UIColor colorWithHue:0.7 saturation:1 brightness:0.4 alpha:1];
cell.detailTextLabel.text=[plot objectAtIndex:indexPath.row];
cell.detailTextLabel.font=[UIFont systemFontOfSize:11];
cell.detailTextLabel.numberOfLines=6;
return cell;
}
Ответы
Ответ 1
Поместите это где-нибудь после успешной загрузки данных:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
Это устраняет проблему вызова обновления GUI , пока вы не находитесь в основном потоке.
Этот код использует технологию GCD от Apple, чтобы заставить функцию данных перезагрузки работать в основном потоке. Узнайте больше о
Concurrency Руководство по программированию для лучшего понимания (это довольно большое поле, так что это трудно объяснить в комментарии)
Во всяком случае, это не очень рекомендуется, если вы не понимаете это хорошо, потому что это приводит к сбою программы в некоторых редких случаях.
Ответ 2
Для быстрого 3:
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.reloadData()
})
Для быстрого 2:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
Ответ 3
Все, что вам действительно нужно сделать, - это когда вы обновляете свои исходные данные, звоните
[tableView reloadData];
Так как это происходит синхронно, вы должны, вероятно, иметь такую функцию, как
-(void) updateTable
{
[tableView reloadData];
}
и после добавления данных в ваш запрос на скачивание
[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:NO];
Ответ 4
U может использовать [cell setNeedsDisplay];
например:
dispatch_async(dispatch_get_main_queue(), ^{
[cell setNeedsDisplay];
[cell.contentView addSubview:yourView];
});
Ответ 5
У меня была такая же проблема! Я хотел, чтобы UITableView был полностью заполнен до появления контроллера представления. Сообщение Envil предоставило мне необходимую мне информацию, но мое решение оказалось другим.
Вот что я сделал (реконструировал, чтобы соответствовать контексту вопроса).
- (void)viewDidLoad {
[super viewDidLoad];
[self performSelectorInBackground:@selector(fethchData) withObject:nil];
}
- (void)viewWillAppear {
[tableView reloadData];
}
Ответ 6
У меня была эта проблема, и я имел дело с ней весь день.
Я использую статические ячейки и reloadData вызывает неправильную загрузку, она отображает только видимые ячейки и удаляет другие.
Я заметил, что когда я прокручивал вниз (y в отрицательном значении) ячейки, где загружался правильно, поэтому я написал этот код, и он сработал, хотя я не люблю пропускать его таким образом.
Стреляйте, если найдете лучшее решение.
-(void)reloadTableView{
CGPoint point = self.tableSettings.tableView.contentOffset;
[self.tableSettings.tableView reloadData];
[UIView animateWithDuration:.001f animations:^{
[self.tableSettings.tableView setContentOffset:CGPointMake(point.x, -10)];
} completion:^(BOOL finished) {
[UIView animateWithDuration:.001f animations:^{
[self.tableSettings.tableView setContentOffset:point];
} completion:^(BOOL finished) {
}];
}];
}
Ответ 7
Во-первых, эта полурешенная моя проблема. Я хочу округлить углы изображения в ячейке таблицы. Диспетчер асинхронно исправил проблему для некоторых, но не для всех изображений. Есть идеи?
Во-вторых, я думаю, вы должны избегать создания сильного опорного цикла с помощью списка захвата закрывающий следующим образом:
DispatchQueue.main.async(execute: { [weak weakSelf = self] () -> Void in
weakSelf!.tableView.reloadData()
})
Смотрите: https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID52