2012-06-04 2 views
51

Я пытаюсь загрузить анализируемые данные в ячейки, но проблема в том, что это происходит синхронно, а UitableView не отображается, пока данные не закончили загрузку. Я попытался решить проблему с помощью функции performSelectorInBackground, но теперь данные не загружаются в ячейки до начала прокрутки. Вот мой код:Данные не загружаются в UITableView до тех пор, пока я не прокручу

- (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; 


} 
+0

только видимые ячейки будут загружены, клетки остальные будут как только они появятся после прокрутки. – rishi

ответ

123

Поместите это где-то после того, как данные загружены успешно:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.tableView reloadData]; 
}); 

Это решить проблему вызова обновления GUI , пока вы не в главном потоке.

Этот код использует технологию GCD от Apple, чтобы заставить функцию данных перезагрузки работать в основном потоке. Узнайте больше о Concurrency Programming Guide для более глубокого понимания (это довольно большое поле, так что это трудно объяснить в комментарии) Во всяком случае, это не очень рекомендуется, если вы не понимаете это хорошо, потому что это приводит к сбою программы в некоторых редких случаях.

+0

Спасибо. Я поспешно переместил некоторые вещи и не понял, что моя загрузка данных была в другом потоке и, следовательно, моя reloadData. Спасибо, что помогли мне вернуться и проанализировать вещи. – chadbag

+0

Спасибо! Это просто решило действительно раздражающую ошибку, которая у меня была. –

+1

ОГРОМНАЯ ПОМОЩЬ! спасибо – Greg

9

Все, что вам действительно нужно сделать, это какое-то время у вас есть обновление Админцетр данных, вызовите

[tableView reloadData]; 

Поскольку это происходит синхронно, вы должны, вероятно, функция как

-(void) updateTable 
{ 
    [tableView reloadData]; 
} 

и после добавления данных в загрузки вызова

[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:NO]; 
+0

В нем указано «Неизвестный приемник tableView» – Benjamen

+0

В качестве примера используется код, я не знаю точной структуры вашего класса или макета представления. Дело в том, что вам нужно получить ссылку на представление таблицы (если ваш класс является экземпляром или подклассом UITableViewController, вы должны просто иметь self.tableView) и вызывать метод 'reloadData' на нем –

+0

В UITabbleviewController это будет ** self.tableView ** – LavaSlider

1

У меня была такая же проблема! Я хотел, чтобы UITableView был полностью заполнен до появления контроллера представления. Сообщение Envil предоставило мне необходимую мне информацию, но мое решение оказалось другим.

Вот что я сделал (реконструировал, чтобы соответствовать контексту вопроса).

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self performSelectorInBackground:@selector(fethchData) withObject:nil]; 
} 

- (void)viewWillAppear { 
    [tableView reloadData]; 
} 
2

U можно использовать [cell setNeedsDisplay]; , например:

dispatch_async(dispatch_get_main_queue(), ^{ 
      [cell setNeedsDisplay]; 
      [cell.contentView addSubview:yourView]; 
     }); 
1

У меня была эта проблема, и я имел дело с ним весь день.

Я использую статические ячейки и 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) { 

      }]; 
     }]; 
} 
+0

Это сработало для меня. Дайте мне знать, если вы выяснили фактическую проблему –

13

Для быстрой 3:

DispatchQueue.main.async(execute: {() -> Void in 
       self.tableView.reloadData() 
      }) 

Для быстрой 2:

dispatch_async(dispatch_get_main_queue(), {() -> Void in 
       self.tableView.reloadData() 
      }) 
+0

bro swift 3 хорошо работает !! ... Спасибо –

+0

@MayPhyu Добро пожаловать :) – Hamid

0

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

Во-вторых, я думаю, вы должны избегать создания сильного опорного цикла с помощью списка захвата закрытия, как это:

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

+0

Это исправило мою проблему: DispatchQueue.main.async (выполнить: {[weak weakCell = cell]() -> Пустота в weakCell! .imageView! .layer.cornerRadius = cell.imageView! .frame.width/4.0 weakCell! .imageView! .clipsToBounds = true }) – user3590685

Смежные вопросы

 Смежные вопросы