I have a custom tableview cell and am getting data from the network 10 at a time. As users scroll down it fetches 10 more and displays the content.
Sometimes, my fetch can be a bit slow (>3-4 secs) and during that instance(when a fetch is currently happening), if my custom tableview cell is clicked (on the visible rows) then the app crashes at the following line. (I followed the example here to expand/collapse my cell and show more content)
Obviously the tableview:reloadRowsAtIndexPaths is called as and when network fetch is done and making changes to tableview data..so how can i fix this issue ?
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"ROW SELECTED..%ld",indexPath.row);
if (self.selectedIndex ==indexPath.row)
{
self.selectedIndex=-1;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
return;
}
if (self.selectedIndex!=-1){
NSIndexPath *prevPath = [NSIndexPath indexPathForRow:self.selectedIndex inSection:0];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:prevPath] withRowAnimation:UITableViewRowAnimationFade];
}
self.selectedIndex=(int)indexPath.row;
//[self.tableView beginUpdates];
//app crashes at this line !!
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//[self.tableView endUpdates];
}
The exception i am getting is
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (10) must be equal to the number of rows contained in that section before the update (11), plus or minus the number of rows inserted or deleted from that section (1 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
If self.selectedIndex!=-1 is true, then you are going to ask the tableview to reload twice. I have a few suggestions:
put all those reload calls into dispatch blocks, so you don't issue them directly in a delegate method
aggregate the last two reloads into a single reload by using a mutable array, but again, dispatch to the main queue.
Also, add some logs. What happens if prevPath is out of range - that cell isn't valid any more?
EDIT: your answer is here:
"The number of rows contained in an existing section after the update (10) must be equal to the number of rows contained in that section before the update (11), plus or minus the number of rows inserted or deleted from that section (1 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)."
Before the update you had 10 items in this section.
After the update you had 11 items in this section
you inserted one and deleted one (this is not shown in your code snippet)
you didn't move any in or out
So you have one more item in your section (told to the tableview in the delegate method) than insertions (net 0) and moves (net 0).
Related
I am getting error on following line:
[self.tableView deleteRowsAtIndexPaths:#[indexpath]] withRowAnimation:UITableViewRowAnimationFade];
Also the cell at that indexPath is nil since that table cell is not visible on tableview due to tableview scrolled:
TableCell *cell = (TableCell *)[self.tableView cellForRowAtIndexPath:indexPath];
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 5. The number of rows contained in an existing section after the update (25) must be equal to the number of rows contained in that section before the update (28), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Let's say you want to remove item at index 5 in section 0, your code will look like this, In Swift
tblList.beginUpdates()
data.remove(at: 5)
tblList.deleteRows(at: [IndexPath(row: 5, section: 0)], with: .fade)
tblList.endUpdates()
Objective-C code will look like this,
[_tblList beginUpdates];
[data removeObjectAtIndex:5];
[_tblList deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:5 inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
[_tblList endUpdates];
Hi I am working with the chat app every thing is working fine.Now I need to delete a message.For that i am using long Gesture on tableview.But My Tableview is configured like sections are Dates and messages are Rows.Now when Long Tap on row it is showing Row number not respect to Sections.So I am using below Code it showing the currect index path.Then I am deleting That message in sqlite.But getting error like index Beyond the Exception
CGPoint p = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
id<SOMessage> message = self.conversation[indexPath.section][indexPath.row];
int index = (int)[[self messages] indexOfObject:message];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
} else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
NSLog(#"long press on table view at row %d", index);
}
in the above code, index is my indexapth value for deleting a row.and how i am deleting row in tableview is
[self.tableView deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationFade];
below is my error log
invalid number of rows in section 1. The number of rows contained in an existing section after the update (10) must be equal to the number of rows contained in that section before the update (10), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Not getting you question... you are doing every thing right, if you are able to delete row in sqlite with this then you can even in UITableView.
To delete row directly from table view just add following in your code:
else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
[self.tableView deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationFade];
}
I really didn't get your question but hope this may help :)
I have a UITableView of custom cells. Each cell has an NSTimer that can be set by the user and started by tapping a button. The timers work except when a new cell is added to the TableView. In the unwind method (coming from creating a new object for a new cell) I have to reload the data in the TableView so that the new cell appears. This however reloads all the cells causing any running timer to restart. Is there a way I can add the cell without restarting the running timers?
EDIT:
I have a ViewController that creates a new object and then back in the FirstViewController.m I have an unwind method that should update the tableView with a row for the new object. Using the reloadData method won't work because it reloads all of the cells. I would like to just add a new cell without reloading the entire tableView.
-(IBAction)unwind:(UIStoryboardSegue *)segue {
ABCAddItemViewController *source = [segue sourceViewController];
ABCItem *item = source.object;
if (item != nil) {
[self.objectArray addObject:item];
[self.tableView reloadData];
}
}
To do this I've tried adding these lines instead of [self.tableView reloadData]:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.objectArray indexOfObject:item] inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
However, the app crashes and I get this message:
'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
The number of rows in the tableView is determined by [self.objectArray count] in the numberOfRowsInSection: method.
It is not a good idea to add timers to cells because they are reused. They are views. My recommendation is to create some objects which have the text / info you want to display in these UITableViewCells and add the timers to those objects. This way the timer info is not stored in the cells and they will store state
There is no need to reload entire table for just inserting one cell. You can add the cell like
self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:row inSection:section]] withRowAnimation:UITableViewRowAnimationLeft];
[self.tableView endUpdates];
When I am reloading one section,after deleting last object from array and reloading section
NSIndexSet *indexSet = [[NSIndexSet alloc]initWithIndex:0];
[_LYTPhotosUICreator.getTableViewInstance reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
then I have an exception
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Please let me know where I did wrong.
Invalid update: invalid number of rows in section 1 this means section 1 current number is 0, before is 4, however, you now do update section 0.
Try this way.
[self.tableView beginUpdates];
// remove the objects from data source
// give the according row indexpaths
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
Im a little bit confused about how to add rows to the table view.
I have an array which gets values added to it regularly. I am trying to update the number of rows everytime a new value is added to the array using these lines of code:
// listOfMembers if a
[[self tableView] beginUpdates]; [tableView numberOfRowsInSection:[listOfMembers count]];
[[self tableView] endUpdates];
[[self tableView] beginUpdates];
[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
[[self tableView] endUpdates];
however this does not work to change the number of rows.. may i am misunderstanding how the table updates. I get this error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (5) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
THe crash is on the line:
[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
How should I be updating my table view clearly I am doing this in the wrong way.
Ok so the answer to this problem is to simply call the function reloadData. for example:
[tableViewOutlet reloadData];