I have a nice bug here, specially in slow devices.
I have a UITableView jusk like the ones in the App Store app, with a Load More button at the bottom.
When it is pressed, I load the new info from the server, set the array, and reload the table view. In that info is also the url of the image for each object displayed in the table rows, so when we got it we start donwloading the image. When the image is loaded, I reload the row of the object.
[self.searchResultsTableView reloadRowsAtIndexPaths: [NSArray arrayWithObject: path] withRowAnimation: UITableViewRowAnimationNone];
The problem comes when the row is being reloading because the image was downloaded, and the whole table is doing so cause the user pressed the load more button and more info was gotten. Then I get this error:
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (140) must be equal to the number of rows contained in that section before the update (125), plus or minus the number of rows inserted or deleted from that section (1 inserted, 1 deleted).
Which is perfectly understable, the table was enlarged while the new image row was being updated.
My question is: how can lock it so I do not reload that row until the whole table is reloaded? It would nice something like table.isReloading. I try with a boolean lock, and doing both actions in the main thread, but it did not work ...
Thanks a lot.
Well, a little research in the doc put some more light in all this.
reloadRowsAtIndexPaths:withRowAnimation: Call this method if you want to alert the user that the value of a cell is changing. If, however, notifying the user is not important—that is, you just want to change the value that a cell is displaying—you can get the cell for a particular row and set its new value.
And that is what I did, I got the cell and set the new value for image, instead of reloading the whole of it. I guess it is more efficient also:
AHMyTableViewCell *cell = (AHMyTableViewCell *) [self.myTableView cellForRowAtIndexPath:path];
if ((cell != nil) && ([cell isKindOfClass:[AHMyTableViewCell class]]))
cell.myImageView.image = image;
It does not crash now.
Related
Is there a way to get access to a UITableViewCell that is not currently on screen? I'm trying to update rows that are currently not in view. I am using this collapsable/expandable rows for a UITableView in one of Apple's example codes. I use this:
for (NSInteger row = 0; row < totalRows; row++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:row inSection:section];
OrderTableViewCell *cell = (OrderTableViewCell *)[_tableView cellForRowAtIndexPath:path];
cell.CheckmarkButton.selected = YES;
cell.Symbol.isSelected = YES;
}
My totalRows is correct in that I get the number of rows from the TableView. So I thought I could use that, loop through all the rows, and set some values. However, if I check the state of the rows, the ones that are currently on screen have values and I can change them, but the ones off screen are null and cannot be set. Is there a way I can get around this? Thanks.
Depending on what you want to update you could just update the ith entry in a backing collection.
For example you could have a collection that stores bools corresponding to CheckmarkButton selected. In your loop you could set myArray[row] = YES. In cellForRowAtIndexPath you can do cell.CheckmarkButton.selected = myArray[indexPath.row].
If you want to maintain multiple items for each cell then myArray in the above example could contain instances of an object that holds values relevant to the ith cell.
Well why do you have to update a cell like that... If the cell is out of view, to save memory the system unloads it, and since its not in the view there is no need for you to update the cell directly, rather you should have the state be reflected in such way that when cellForRowIndexPath is called by the table view to load the cell the desired look is shown... The only reason youd want to do what you are doing is if the cell is showing and you need to update the cell, for the user... Even then you can still set your state and call the reloadRowsAtIndexPaths instead of manipulating the cell directly... Hope that helps
When I call this Code
[[self tableView]reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:kSectionShoppingList]] withRowAnimation:UITableViewRowAnimationNone];
HeightForRowAtIndexPath Calls
But in CellForRowAtIndexPath for section 3 row 0 does not call.
Looking for your suggestion.
and it is specific to Device 3g iOS4.0.1.
Is anyone earlier have faced same issue.
Is the cell you are reloading visible ?
Not sure about iOS4.0.1, don't have it installed to test, but on iOS5+, the cellForRowAtIndexPath is not called if the cell is not visible, just tried it in one of my apps.
The issue i have mentioned look like a bug in iOs4.0.1. anyway I have solved it by reloading whole table using reloadData method instead of reloading particular rows.
Make sure your are reloading sections and rows that are visible and corresponding the the right indices in your tableview. Also check that your tableView delegate and datasource are correctly set.
reloadData method as the following comment :
- (void)reloadData; // reloads everything from scratch. redisplays visible rows. because we only keep info about visible rows, this is cheap. will adjust offset if table shrinks
you may also have trouble reloading single rows if your table is mutating, then you should beginUpdate / endUpdate methods
- (void)beginUpdates; // allow multiple insert/delete of rows and sections to be animated simultaneously. Nestable
- (void)endUpdates; // only call insert/delete/reload calls or change the editing state inside an update block. otherwise things like row count, etc. may be invalid.
i am getting images with messages from .net webserver by giving xml input.
that's working fine.
i am sending request for every 3 sec and if any new messages and images are there i just add those messages and images to the array and reload the table view.
That is also fine,But what i need is when i reload table view when ever there is new messages that will be displayed on table view by smooth scrolling the existing row.
same as twitter.
can any one please help me.
Thank u in advance.
if you know the indexPath of newly added row , you could use the below function of UITableView to scroll upto new row with animation (smooth effect).
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
Instead Of completely reloading the table, you should call insertRowsAtIndexPaths:withRowAnimation:
The second option will let you specify how you want it animated
(this will also be much more efficient than reloading all the data every time)
You can do something like the following:
(this makes the assumptions that recievedImageFrom server will be called after the data has already been loaded into the data source object. Also, myDataSourceArray is the array where the data is being stored for the table and myTableView is the UITableView.
-(void)recievedImageFromServer
{
NSUInteger row = [myDataSourceArray count]-1; // This can also be set to 0 if you want
// to insert at the top of the table
NSIndexPath* newIndex = [NSIndexPath indexPathWithIndex:row];
[myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndex]
withRowAnimation:UITableViewRowAnimationTop];
}
It will then request the cell from its data source.
I have a table and row contents(hard coded contents). when i choose one row and see the content and then come back to same table and try to choose another row, it doesn't deselect the first row selection(by default it shows Blue selection-UITableViewCellSelectionStyleBlue), instead both the rows are being in selected mode.
I was hoping, when we choose one row and then choose another row, by default it should unhighlight immediately the previous row selection.
Why and when should it happen?
I tried code 'cell.selectionStyle = UITableViewCellSelectionStyleNone;'
and tableView.allowsSelection=NO;
but no success, these are just not allowing completely from selection view.
I want when one row is selected and then the another is getting selected, the first row selection should be cleared and should show only the current row selection.
Any help please?
In your tableView:didSelectRowAtIndexPath: method or in the method you call when entering edit mode (the one containing [tableView setEditing:YES animated:YES];), add the following line:
[tableView deselectRowAtIndexPath:indexPath animated:YES];
before pushing a new controller.
I am beginner iphone developer I want created table in programatically. In the table we take more than 20 row. But i have some problem that after 11th row the same value repeated.
plz help me with code and other method
You may want to look at this question which is the same problem. In that case, the person was setting the text of the cell only when creating a new cell (when nil was returned from [tableView dequeueReusableCellWithIdentifier:].) It needs to be set every time the tableView:cellForRowAtIndexPath: is called.
when you use reuseIdentifyer, the new cell to display is the cell that has just disappeared. so it will contain all the data from the disappeared cell. for example, if the cell, that has just disappeared, has detailDisclosureIndicator, the new cell will have it too even you don't set it.