I have an issue where I have a UITableViewController and when the view appears I do some calculations asynchronously which should result in the updating of specific rows in the table.
Inside the cellStartEditing function I calculate the necessary rows that need to be updated as follows:
-(void) cellStartEditing:(templateRow *) row{
int Cellowid= row.rowId;
[arrQuestions removeObjectAtIndex:CellRowid];
[arrQuestions insertObject:row atIndex:CellRowid];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow: inSection:0];
[tvQuestion reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
At that time reloadRowsAtIndexPaths Animation gain to 50% CPU Memory ?
Notify about tableview updates before reloading the rows as below:
[tvQuestion beginUpdates];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow: inSection:0];
[tvQuestion reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone]
[tvQuestion endUpdates];
Related
I am trying to insert row at the top of the table. Firstly insert into the data:
[self.myDataArray insertObject:scannedItem atIndex:0];
Then I call reloadData for the table. Item inserted but table scrolls up, item doesn't visible and it is possible to scroll all items out of the top bound. I have no dynamic cells and also have estimatedRowHeight set as const integer(60).
Here is screens for tableview
[self.tableView beginUpdates];
[self.myDataArray insertObject:scannedItem atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
I am doing very usual stuff.
First modifying the data model and then updating the TableView. But sometimes app crashes.
And throws error something like that (depends on insertion or deletion).
Fatal Exception: NSInternalInconsistencyException
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 (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).
Here is my insertion code.
[self.tableView beginUpdates];
[self.stories insertObject:story atIndex:0];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
and Deletion code.
[tableview beginUpdates];
[stories removeObject:story];
NSIndexPath *indexpath = [tableview indexPathForCell:cell];
if(indexpath) {
[tableview deleteRowsAtIndexPaths:#[indexpath] withRowAnimation:UITableViewRowAnimationTop];
}
[tableview endUpdates];
Insertion Code:
[self.stories insertObject:story atIndex:0];
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
Deletion Code:
[stories removeObject:story];
[tableview beginUpdates];
NSIndexPath *indexpath = [tableview indexPathForCell:cell];
[tableview deleteRowsAtIndexPaths:#[indexpath] withRowAnimation:UITableViewRowAnimationTop];
[tableview endUpdates];
Note: You should not add/remove object to an array inside updating your tableview's rows.
Either do [tableview reloadData]; or [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
Also you are doing database operation in-between [self.tableView beginUpdates];
and [self.tableView endUpdates];. It's not proper.
As per the error suggests, there is a mismatch in table view rows and data source of that table view.
I have a UISearchController and i want to select the first row of the searchResultsController tableview on click of search button in the keyboard.
For that I tried implementing
-(void)searchButtonClicked:(UISerachBar*)searchBar {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.searchResultsController.tableView selectRowAtIndexPath: indexPath animated:false scrollPostion:UITableViewScrollPositionNone];
[self.searchResultsController tableview:self.searchResultsController.tableView didSelectRowAtIndexPath: indexPath];
}
but it didn't work for me!!
Then I tried to make a separate method:
-(void) plotPinOnMapWithIndexPath:(NSIndexPath*)indexpath;
and called it in didSelectRowAtIndexPath and in searchButtonClicked method by passing the indexPaths.But the problem is that the cell doesn't get highlighted the way it gets highlighted when user clicks on it.
This works for me, and is correct:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
optionally try this:
[self.tableView:self.tableView didSelectRowAtIndexPath:indexPath];
or you can use Segue to continue with result:
[self performSegueWithIdentifier:"showDetailView" sender:self];
In prepareForSegue method you pass parameters....
It worked!!
-(void)searchButtonClicked:(UISerachBar*)searchBar {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self tableview:self.searchResultsController.tableView didSelectRowAtIndexPath: indexPath];
}
EDIT:
I found this SO thread.
UITableView inserting section at top while scrolling
I have a tableView
I load it with 5 sections initially
Then I scroll up and when section 0 and row 0 is displayed, I load the next 5 sections and insert in table view using
[self beginUpdates];
[self deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
[self insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
[self insertSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone];
[self insertSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationNone];
[self endUpdates];
However my problem is the tableView gets position at section 0 and row 0 after the inserts
but I want to position at last row of last new section inserted (which is section 2 in code above)
I tried this both inside and outside begin/end updates
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:2];
[self scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom animated:YES];
But it does it abruptly.
After inserting sections you can also scroll the table view to the intended index path using
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:2];
[UIView animateWithDuration: 1.0
animations: ^{
[tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}
completion: ^(BOOL finished){
}
];
Note:
1) Insert the above code after [self endUpdates];
2) Please ensure that you keep the animated flag to NO using scrollToRowAtIndexPath: atScrollPosition: animated: while you are using it with UIView's animateWithDuration: animations: completion: API.
3) Also you can calculate the duration based on the distance (content size, height wise for vertical scroll), i.e duration can depend on the distance between source index path and destination index path.
Please try below code.
[self beginUpdates];
/*
Insert your sections
*/
[self endUpdates];
[self performSelector:#selector(scroll) withObject:nil afterDelay:0.1];
-(void)scroll
{
if([Your array count] > 0)
{
[YOURTABLENAME scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:2] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
I Hope above code is work for you.
Thanks
I am creating an iOS app that is set up as a hierarchy of data. I have no issues on the first page adding and deleting objects or even transitioning to the next page. The problem occurs on the second page which is set up exactly like the first. When I press the add button to add an object the program crashes and sends back the error SIGABRT.
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:YES]; << crashes on this line
here is the function add tapped:
- (void)addTapped:(id)sender {
StudentDoc *newDoc = [[[StudentDoc alloc] initWithTitle:#"New Student" rating:0 thumbImage:nil fullImage:nil] autorelease];
[_students addObject:newDoc];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_students.count-1 inSection:0];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:YES];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
}
number of rows in section:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _students.count;
}
I have been under the impression that the count is what is causing the problem, but I have monitored the count and it stays consistent.
Overall I have no idea why it is crashing at this point because the page before it uses the exact same function to add objects on that page. Any ideas?
Normally if you'd messed up your array or row indexes you'd expect an exception to be logged in the console, not a SIGABRT. Have you enabled NSZombies and break-on-exceptions in Xcode? That may help to diagnose the issue.
You should put insert row at index path between begin updates and end updates block.
- (void)addTapped:(id)sender {
StudentDoc *newDoc = [[[StudentDoc alloc] initWithTitle:#"New Student" rating:0 thumbImage:nil fullImage:nil] autorelease];
[_students addObject:newDoc];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_students.count-1 inSection:0];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:YES];
[self.tableView endUpdates];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
}
I've done almost the same, tho I split it into 2 lines:
NSInteger idx = [_students count] - 1;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
I wonder if that would make a difference.
You're adding an object to the data source, but replacing an existing row in the table, not adding one, resulting in one row in the indexPath but 2 items in the data source array.
For instance, if you have one item in _students, you'll have one index path, {0,0}. When you add a row, you're adding it at indexPath {_students.count - 1, 0}, which would be {1 - 1, 0} or {0, 0}. Your data source should match any indexPaths you insert or remove, and in your case you're always ending up with one more item in your data source than you add/remove.
If you always want to add an item, instead of:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_students.count-1 inSection:0];
You want:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_students.count inSection:0];