Question

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
}
Was it helpful?

Solution

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

OTHER TIPS

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...

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];
        }); 
}

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top