Dutchie432
Dutchie432

Reputation: 29160

What's with [UITableView reloadData]?

I have an application that has a UITableView. This UITableView is populated by an NSMutableArray being held (as a property) in the appDelegate. You can think of this as an email window. It lists messages in a subclassed UITableViewCell. When a new message appears, I have all the code done which downloads the message, adds the data to the appDelegate's NSMutableArray which holds all of the messages. This code is working fine.

Now, once the new message is downloaded and added to the array, I am trying to update my UITableView using the following code, however - the UITableView's delegate functions do not get called.

The odd thing is when I scroll my UITableView up and down, the delegate methods finally get called and my section headers DO change (they show the message count for that section). Shoudn't they update in real-time and not wait for my scrolling to trigger the refresh? Also, the new cell is never added in the section!!

Please Help!!

APPDELEGATE CODE:

[self refreshMessagesDisplay]; //This is a call placed in the msg download method

-(void)refreshMessagesDisplay{
    [self performSelectorOnMainThread:@selector(performMessageDisplay) withObject:nil waitUntilDone:NO];
}

-(void)performMessageDisplay{
    [myMessagesView refresh];
}

UITableViewController Code:

-(void) refresh{
    iPhone_PNPAppDelegate *mainDelegate = (iPhone_PNPAppDelegate *)[[UIApplication sharedApplication] delegate];

    //self.messages is copied from appDelegate to get (old and) new messages.
    self.messages=mainDelegate.messages;

    //Some array manipulation takes place here.

    [theTable reloadData];
    [theTable setNeedsLayout];  //added out of desperation
    [theTable setNeedsDisplay];  //added out of desperation
}

Upvotes: 22

Views: 48037

Answers (4)

nooitaf
nooitaf

Reputation: 1468

If you call reloadData from within a dispatched method, make sure to execute it on the main queue.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0), ^(void) {

    // hard work/updating here

    // when finished ...
    dispatch_async(dispatch_get_main_queue(), ^(void) {
        [self.myTableView reloadData];
    }); 
});

..same in method form:

-(void)updateDataInBackground {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0), ^(void) {

        // hard work/updating here

        // when finished ...
        [self reloadTable];
    });
}

-(void)reloadTable {
       dispatch_async(dispatch_get_main_queue(), ^(void) {
            [myTableView reloadData];
        }); 
}

Upvotes: 6

h4xxr
h4xxr

Reputation: 11475

You could try putting a delay on the reloadData call - I had a similar problem when I was trying to get my tableview to update when reordering cells, except that the app crashed if I called reloadData during it.

So something like this might be worth a try:

Refresh method:

    - (void)refreshDisplay:(UITableView *)tableView {
    [tableView reloadData]; 
}

and then call it with (say) a 0.5 second delay:

[self performSelector:(@selector(refreshDisplay:)) withObject:(tableView) afterDelay:0.5];

Hope it works...

Upvotes: 12

Marc Charbonneau
Marc Charbonneau

Reputation: 40515

Have you tried setting a breakpoint in your refresh method just to be sure your messages array has the correct content before calling reloadData?

Upvotes: 0

smorgan
smorgan

Reputation: 21599

As a sanity check, have you verified that theTable is not nil at that point?

Upvotes: 29

Related Questions