21

I have a simple app that downloads search results in XML when the user types in a UISearchBar. The download+parsing is threaded and once done it fires an NSNotification to tell the ViewController with the table view to [tableView reloadData];

Here is the code that receives the notification fired once results are in:

- (void)receivedResults:(id)notification {
    results = [notification object];
    DLog(@"Received %i results",[results count]);
    [[self tableView] reloadData];
}

I get the log output "Received 4 results", but the table view doesn't reload the data until I scroll/drag it a couple pixels. I am using the built-in UITableViewCellStyleSubtitle cell style and im not changing the height or ding anything fancy with the table view.

What am I doing wrong?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Maciej Swic
  • 11,139
  • 8
  • 52
  • 68
  • results is of course an instance variable and the source for the table view, otherwise the code above would not work even when pulling the table view around after search. – Maciej Swic Feb 11 '11 at 11:25
  • your sure [self tableView] does not return nil? Could be the reason why reload does not respond, but the cellForRowAtIndexPath does. That method is invoked by the delegate. – Mats Stijlaart Feb 19 '11 at 09:04

5 Answers5

66

I was able to get the same thing to work. But the issue was that the reload data needed to be called on main thread.

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

I think this is more practical than the performSelectorOnMainThread option

Malloc
  • 15,434
  • 34
  • 105
  • 192
The Lazy Coder
  • 11,560
  • 4
  • 51
  • 69
  • Don't know if it's that much more practical, however Apple does recommend GCD in favor of the performSelector... pattern. – Maciej Swic Feb 28 '13 at 09:22
  • @MaciejSwic This should be the correct solution to this specific question. The problem is that the OP is trying to change the UI on a background thread, most likely he forgot to exit out of it. You shouldn't call performSelectorOnMainThread just as a work-around. – JRam13 Oct 14 '14 at 16:48
  • This did not fix it for me. My problem is very similar, but with the variation that the cells only show their content when they have been scrolled completely out of view and back into view. I'm completely baffled by this so far... :-( – Erik van der Neut May 12 '15 at 09:54
  • @ErikvanderNeut Hi, Did you solved this problem? I am also facing the same problem – Manimaran Jun 22 '16 at 14:24
  • Hi @Manimaran -- I never found a proper solution to the underlying problem, but with a hack I was able to get it to look as if there was no problem. Once that seemed robust enough, I left it at that. My hack was to scroll the table back and forth before the showing the view. My memory is a bit vague now on the details, but basically I just implemented in code a instant scroll back and forth to make sure that the cells had been completely scrolled out of view and back into view before actually showing it on the screen. It sounds absurd, but that ugly hack did fix the problem :-/ Very strange... – Erik van der Neut Aug 16 '16 at 09:34
34

Call

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

instead of

[self.tableview reloadData]
Andrew
  • 690
  • 7
  • 11
4

My problem was that I was posting a NSNotification from a background thread. To avoid this, simply wrap your postNotificationMethod in a dispatch_async method like this:

dispatch_async(dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"FinishedDownloading" object:result];
});

When this notification will be received, the tableView.reloadData will be called on the main thread.

BalestraPatrick
  • 9,944
  • 4
  • 30
  • 43
0

I have the same problem, and I have tried all the solution I can find on google. But All of them don't work.

At last I found that I add observer before viewDidLoad, and then [self.tableView reloadData] is not working.

First I call the setObserverForUserInfoDatabase in the viewDidLoad of my root navigation view controller. Because I think it was called earlier. The function is like this:

- (void)setObserverForUserInfoDatabase:(NSString *)name {
    [[NSNotificationCenter defaultCenter] addObserverForName:name
                                                      object:nil
                                                       queue:nil
                                                  usingBlock:^(NSNotification *note) {
                                                      [self loadUserInfo];
                                                      [self.tableView reloadData];
                                                      NSLog(@"User Panel Notification \n %@", self);
                                                  }];}

Then I move the code into viewDidLoad of the viewController itself.

- (void)viewDidLoad {
    NSLog(@"View Did Load");
    [super viewDidLoad];

    [self setObserverForUserInfoDatabase:UserInfoDataBaseAvailabilityNotification];
}

And then everything works fine.

I don't know the reason yet. If anyone knows please tell me.

wgr
  • 513
  • 4
  • 9
0

reload your tableView in viewWillLayoutSubviews

goto
  • 7,908
  • 10
  • 48
  • 58
Krishna Kirana
  • 438
  • 4
  • 10