Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reloadData calls numberOfSections, numberOfRows, not cellForRowAtIndexPath

first of all sorry if this isn't formatted correctly, first time doing this. I've been using stackoverflow to find help for a long time now and it's been very helpful (thank you all), but this is the first time I've posted a question of my own. This question has been asked many times, but when I call [myTable reloadTable] the methods numberOfSectionsInTableView and numberOfRowsInSection are called but not cellForRowAtIndexPath.

Every answer I've seen when searching has been a variation of: 1) The tableView is nil 2) numberOfRowsInSection is 0 3) tableView's delegate/data source not set 4) calling reloadTable on the wrong uiTableView.

None of these are the case for me so I'm wondering what else could be wrong.

What I'm trying to do: I have a custom uitableviewcell with a button on it, when the button is pressed I want to change the attributes of the cell (for an example, let's just say I want to change the cell title to "Button Pressed"). I then want to pause for a moment and then delete the cell.

Not sure if this is important, but my tableView is inside a UIViewController, and the viewController is the delegate and dataSource.

I have a method (below) that fires when the button is pressed and the cell attributes are changed as necessary, however when I try to refresh the table to show the changes it doesn't work. The first time [remTable reloadData] is called, numberofsectionsintableview and numberofrowsinsection are called but not cellforrowatindexpath. However, the second time [remTable reloadData] is called all three methods are called and everything works correctly.

doneCell.remName.text=@"BUTTON PRESSED";
[remTable reloadData];
NSLog(@"sleep");
sleep(1);
[remList removeObject:doneReminder];
[remTable reloadData];

To test this I put nslog statements at the beginning of numberofsections, numberofrows and cellforrow, the output is the name of the method followed by the number (for numberofsections/numberofrows).

Output:

numberofsections 1
numberofrows 3
sleep
numberofsections 1
numberofrows 2
cellforrow

Any ideas as to why cellforrow's not being called the first time? Thanks in advance, please let me know if there's anything else I can add to clarify.

like image 550
jasonm Avatar asked Feb 16 '12 03:02

jasonm


1 Answers

A table view doesn't actually request its cells until it needs to display them. When you call reloadData, it will immediately request the number of sections and rows so that it knows how big it needs to be. It doesn't ask for the cells themselves until it is asked to display itself. Views are automatically displayed as necessary at the beginning of each run loop.

Execution doesn't return to the run loop until your code returns. When you call sleep, you don't execute any code, but you also don't return. This means the run loop doesn't get a chance to display the table, so it never asks for any cells. What you need to do is return from your method and ask that another method gets called in 1 second to remove the doneReminder. An easy way to do this is to use the performSelector:withObject:afterDelay: method. This method adds a timer which will call the method you requested after the given delay, which means you can return to the run loop and let the table display.

doneCell.remName.text=@"BUTTON PRESSED";
[remTable reloadData];
[self performSelector:@selector(removeDoneReminder) withObject:nil afterDelay:1.0];
- (void)removeDoneReminder {
    [remList removeObject:doneReminder];
    [remTable reloadData];
}

If remlist and remTable are not instance variables, you can use the withObject: parameter to send them to the removeDoneReminder method.

like image 78
ughoavgfhw Avatar answered Nov 15 '22 09:11

ughoavgfhw