reloadData not working with UITableView

I have some arrays which I update throughout my program and my UITableView needs to reflect these changes. I have the dataSource and delegate set properly because I can edit the UITableView. My problem is that when I call the reloadData function, nothing changes. I know my arrays have data in them because if I NSLog the count then I get more than 0.
I've put breakpoints in the UITableView controller and it looks like the reloadData is just getting ignored. The breakpoints only fire once when the view loads up, not when reloadData is called.
I'm declaring the UITableView in the header file like this

@interface FriendsTableController : UITableViewController {
IBOutlet UITableView * tblView;
}

Then in the .m file I've got this:
@synthesize tblView;

I'm trying to call the reloadData like this:
[tblView reloadData];

Have I over looked something?
Thanks,
Tom

Macbook 13.3", Mac OS X (10.5.6)

Posted on Dec 24, 2008 12:47 PM

Reply
47 replies

Dec 28, 2008 1:04 PM in response to harrytheshark

I'd suggest you to look on the very good how-to example, called EditableDetailView, you'll learn from there a lot on how to handle table issues. But in short, you need to create an array of index paths like that:


NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];

for (ind = beginIndex; ind <= endIndex; ind++) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:ind inSection:0];
[insertIndexPaths addObject:newPath];
}


then you can call the function:

[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];


all this before reloadData

Message was edited by: navac

Dec 29, 2008 3:25 AM in response to navac

Okay now I've got this as my function
-(void)refreshTableWithTags:(NSArray)myArray:(NSArray*)mySecondArray:(NSArray*)myThirdArray:(NSArray)myLastArray {

anotherArray = [[NSArray retain] init];
anotherSecondArray = [[NSArray retain] init];
anotherThirdArray = [[NSArray retain] init];
anotherLastArray = [[NSArray retain] init];
anotherArray=myArray;
anotherSecondArray=mySecondArray;
anotherThirdArray = myThirdArray;
anotherLastArray = myLastArray;



NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
NSIndexPath * ind;
NSIndexPath * beginIndex = 0;
NSIndexPath * endIndex = [anotherArray count];
for (ind = beginIndex; ind <= endIndex; ind++) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:ind inSection:0];
[insertIndexPaths addObject:newPath];
}

[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];


[[self tableView] reloadData];
}

And in the numberOfRowsInSection bit

//This gives me more than 0 when after the reloadData is called so I know the array doesn't have nothing in it
NSLog([NSString stringWithFormat:@"Number of rows = %i",[tag count]]);
return [anotherArray count];

And finally in the bit where you make the cells

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}

// Set up the cell...

cell.text = [[NSString alloc] initWithFormat:@"%@ (%@)",[anotherArray objectAtIndex:indexPath.row],[anotherSecondArray objectAtIndex:indexPath.row]];
return cell;
}


This does nothing at all, even with the insertRows bit.
Tom

Dec 29, 2008 6:19 AM in response to harrytheshark

Hopefully you know what is the difference between value & the pointer on value...
How do you expect this to work? When you create new path it requires a value of integer as its parameter, not a pointer on path. Probably when such a code compiles you have a plenty of warnings. Be sure that you take care and fix warnings, because sometimes it can be a cause of crash...


NSIndexPath * ind;
NSIndexPath * beginIndex = 0;
NSIndexPath * endIndex = [anotherArray count];
for (ind = beginIndex; ind <= endIndex; ind++) {
NSIndexPath *newPath = [NSIndexPath indexPathForRow:ind inSection:0];
[insertIndexPaths addObject:newPath];
}

[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];


Here is an interface:

+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section;


as you see arguments for row & sections are of type NSUInteger.

second, path is zero-based, so your loop should work till ind < endIndex (basics of C programming)

Dec 29, 2008 7:50 AM in response to navac

Yeah I've no idea why I set them as NSIndexPaths!
This is what I'm using now
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
int ind;
int beginIndex = 0;
int endIndex = [tag count];
for (ind = beginIndex; ind < endIndex; ind++){
NSIndexPath *newPath = [NSIndexPath indexPathForRow:ind inSection:0];
[insertIndexPaths addObject:newPath];
}
[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];
[[self tableView] reloadData];
Now the program crashes here

self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];
Saying this

* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'


I'm not getting any warnings before running.
Tom

Dec 29, 2008 2:06 PM in response to harrytheshark

you should be able to do what you want without using "insertRows" or "deleteRows". As navac stated, "insertRowsAtIndexPaths:withRowAnimation:" is tricky to work with so it would be silly to spend all this time trying to get it to work when you don't really need it. I don't know...maybe it would be better to use it (plus it's always a good learning experience trying new things). Do you want to add EXTRA rows (or sections) to your table view besides the amount of rows already there?? Can the user can add items(rows) to that section (like the EditableDetailView sample)?? That is usually when I use those methods. If your table view ONLY consists of rows determined by the amount of items in your array and is not editable, then you probably don't need to use "insertRows" (i'm not saying you can't use it for this scenario just that you don't need to).

One of my apps in the AppStore (something I threw together for a friend and figured I share with everybody) reloads the table view, after it is already loaded, everytime the user pushes a button and doing it this way, the added rows show up. It's called "SmokeTrack" and it's free if you want to see that it can be done.
Is this what you're looking for?? Does the user have to hit a "refresh button" or does the app refresh on it's own??

If it refreshes on its own as the user enters the view then putting it in your "viewWillAppear" method should definitely work...

By the way..just for future knowledge...
I find it better when I am using "insertRowsAtIndexPaths:withRowAnimation:" to use it between a table view updates block instead of reloading the data like you have.
For example:


[tblView beginUpdates];
if(self.editing) {
[tblView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}
else {
[tblView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}

[tblView endUpdates];


you get a smoother transition this way.

Dec 29, 2008 3:27 PM in response to harrytheshark

Well, there really isn't anything to it...just added a string to the array each time action is called. My actual code was a little different cuz like you saw, my app uses a formatted date string instead of a plain string like I used below but otherwise all I did was:
(based on using your "anotherArray" since "numberOfRows" is determined by it's count...)


-(IBAction)addTotal:(id)sender
{
NSString *string = @"Row #";
[anotherArray addObject:string];
[tblV reloadData];
}


and the button you saw is tied to this action in IB so I didn't have to configure it's selector programmatically.

In your cellForRowAtIndexPath, configure cell text like so:


cell.text = [NSString stringWithFormat:@"%@%i", [anotherArray objectAtIndex:indexPath.row], indexPath.row];


and as you already have in your numberOfRowsInSection:


return [anotherArray count];


Very simple, right?? Like this, each time you push the button, a row is added. Now, I know your table view is getting it's data in a bit more of a complex way than just pushing a button but you might have to start of with something similar. When having trouble getting something to work, it's best to just start off really simple and work your way up (ya know, "baby steps").
If I were you, I wouldn't even try to get the data from the website. I would comment that part out and start simple. Maybe tie the table view to a button for now and increment your array someway simple just so you can see that 'reloadData' is being called. Once you got it working there, then add more pieces to the puzzle until you got everything working together.
It's much easier to troubleshoot (or debug) that way then trying to do it with everything already in place (just my opinion)

Dec 29, 2008 4:06 PM in response to bones237

Okay this is becoming daft now!
I've got a button set up, the UITableView now is set up to update when this button is pushed and has nothing to do with getting data from the web.

- (IBAction)addRowButton:(id)sender
{
NSString *string = @"Row #";
[anotherArray addObject:string];
[[self tableView] reloadData];
}

Then for the row count bit

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog([NSString stringWithFormat:@"Number of rows = %i",[anotherArray count]]);
return [anotherArray count];
}

Every time I click the button I get this in the log "Number of rows = 1" then when I click it again "Number of rows = 2" etc.
The tableview is definately reloading but still there are no cells!!
Is there any reason why this would be happening!?
Tom.

Dec 29, 2008 4:26 PM in response to harrytheshark

Right I've done some more messing with the code and I've got this now

- (IBAction)addRowButton:(id)sender
{
anotherArray = [[NSMutableArray alloc] init];
NSString *string = @"Row #";
[anotherArray addObject:string];
[tblView reloadData];
}
This finally adds a row! However, I know because I've got the
anotherArray = [[NSMutableArray alloc] init];

inside the button push it resets everytime, where's the best place to put this bit of code. Without it, the table doesn't update with any rows at all.
Tom.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

reloadData not working with UITableView

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.