Borut Tomazin
Borut Tomazin

Reputation: 8138

UITableView reloadData - cellForRowAtIndexPath not fired

I have splitViewController which has as MasterViewController some viewController and as DetailViewController some tableViewController. When I push a button on masterViewController I want to show new tableViewController in detailViewController instead of existing one.

So I did like this:

SearchDetailViewController *searchDetailViewController = [[SearchDetailViewController alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *searchDetailNavigationController = [[UINavigationController alloc] initWithRootViewController:searchDetailViewController];

After that I'm passing data to show in new tableController:

[searchDetailViewController passInSearchResults:listOfItems];

After that I "push" new controllers to splitViewController:

[searchSplitViewController setViewControllers:[NSArray arrayWithObjects:self.navigationController, searchDetailNavigationController, nil]];

In the target tableViewController method "passInSearchResults" data is passed and I also call reloadData. Method looks like that:

- (void)passInSearchResults:(NSMutableDictionary *)searchResults {
    self.searchResultList = searchResults;
    NSLog(@"Data is passed in: %@",self.searchResultList);
    [self.tableView reloadData];
    //[self.tableView setNeedsDisplay];
}

Console: Data is passed in: [here I get the exact data I want and it seems just right].

After this I see that method "numberOfRowsInSection" is fired:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSLog(@"Setting table length: %i",[self.searchResultList count]);
    return [self.searchResultList count];
}

Console: Setting table length: [here I get proper length]

The problem is that the table is not filled with passed data and method "cellForRowAtIndexPath" is not called.

How can it be that on reloadData method "numberOfRowsInSection" is fired but not method "cellForRowAtIndexPath"... ???

Thanks

Upvotes: 9

Views: 10330

Answers (7)

andrejs
andrejs

Reputation: 572

Check if you are in main thread when calling [self.tableView reloadData];

- (void)passInSearchResults:(NSMutableDictionary *)searchResults {
 if ([NSThread isMainThread]) {
    self.searchResultList = searchResults;
    NSLog(@"Data is passed in: %@",self.searchResultList);
    [self.tableView reloadData];
}
else {
    [self performSelectorOnMainThread:@selector(passInSearchResults:) searchResults waitUntilDone:NO];
}

}

Upvotes: 10

NDB
NDB

Reputation: 618

In my case the problem was that the reloadData() function was not called from the main thread.

I have changed this by placing it in a dispatch_async() function, which solved the problem:

dispatch_async(dispatch_get_main_queue(), {
    self.tableView.reloadData()
})

Hope this helps others.

Upvotes: 3

Max B.
Max B.

Reputation: 871

My "AutoLayouted" UITableView did not call cellForRowAtIndexPath on reloadData, because I set the frame by mistake.

_tableView = [[UITableView alloc] initWithFrame:self.view.frame];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;

By changing it to CGRectZero, it worked..

_tableView = [[UITableView alloc] initWithFrame:CGRectZero];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;

Upvotes: 0

Timur Kuchkarov
Timur Kuchkarov

Reputation: 1155

Also you can be allocating table in init[With...] method of viewController and also wired up same property in IB. This way it's possible that numberOf... delegate methods are called and cellForRow... does not.

Upvotes: 0

jimmyb
jimmyb

Reputation: 256

Check your numberOfRows, if it is 0, there are no cells to display.

Upvotes: 4

Nikita Ivaniushchenko
Nikita Ivaniushchenko

Reputation: 1435

I had the same problem, but decision was very simple. First of all, could you try to scroll table down? tableView:cellForRow... should be called. Check for headers' heights and contentOffset for tableView.

Upvotes: 1

Buchannon
Buchannon

Reputation: 1691

How can it be that on reloadData method "numberOfRowsInSection" is fired but not method "cellForRowAtIndexPath"... ???

After spending a day with the same(ish) issue, I think we found a bug here. I did find a hack/workaround though.

If I alter the array (adding/removing values or completely building it again) that is used in my cellForRowAtIndexPath method, it seems to correctly call cellForRowAtIndexPath again when you reloadData.

For example, in my cellForRowAtIndexPath I have something like:

cell.textLabel.text = [[[self.searchResultsArrayWithSections objectAtIndex:indexPath.section] objectForKey:@"rowValues"] objectAtIndex:indexPath.row];

    return cell;

I also have a method to build this array that gets called on viewDidLoad:

    - (NSMutableArray *)splitIntoSectionsWithAlphabet:(NSMutableArray *)myArray 
{    
NSString *letters = @"abcdefghijklmnopqrstuvwxyz";
NSMutableArray *content = [NSMutableArray new];

//code to build array here, nothing special really

return content;
}

So I noticed that if I specifically call this method again on my searchResultsArrayWithSections array before calling reloadData, it actually calls all of the UITableViewDelegate methods correctly! (like I said, hack but it works!)

//dirty hack, bug with cancel button and not realoding data, seems we have to modify this array before it will work correctly
self.customerListArrayWithSections = [self splitIntoSectionsWithAlphabet:self.customerListArray];
[self.customerListTv reloadData];

Upvotes: 4

Related Questions