Whenever I click on my table view row to insert a large row below it (370px) it freezes, but only if the row I am clicking on is near the bottom of the screen. The CPU usage goes up to 100% and memory continues to increase but no error.
I have already viewed this question and this didn't help UITableView insertRowsAtIndexPaths:WithRowAnimation without freeze UI
here is my code -- self.sectBool basically tracks whether or not we have inserted the row
else if(indexPath.row == 0 && indexPath.section == 4){
self.sectBool = !self.sectBool;
NSMutableArray *indexPaths = [NSMutableArray array];
[indexPaths addObject:[NSIndexPath indexPathForRow:1 inSection:4]];
if (!self.sectBool) {
dispatch_async(dispatch_get_main_queue(), ^{
//[self.tableview reloadData];
[self.tableview beginUpdates];
[self.tableview insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:1 inSection:4]]
withRowAnimation:UITableViewRowAnimationRight];
[self.tableview endUpdates];
//[self.tableview reloadData];
});
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
//[self.tableview reloadData];
[self.tableview beginUpdates];
[self.tableview deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:1 inSection:4]]
withRowAnimation:UITableViewRowAnimationRight];
[self.tableview endUpdates];
//[self.tableview reloadData];
});
}
}
any help is much appreciated!
Related
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.
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 can's seem to be able to remove all table rows. What seems to happen is that only the cells that are in view are removed and then the ones that were out of view move up. Also checked and my data source contains only the cels that are in view at the time of deletion. Heres the code
NSMutableArray *left = [[NSMutableArray alloc]init];
NSMutableArray *right = [[NSMutableArray alloc]init];
for(int i=0;i<dataSource.count;i++){
[dataSource removeObjectAtIndex:i];
NSIndexPath *ip = [NSIndexPath indexPathForRow:i inSection:0];
if(i%2==0)
[left addObject:ip];
else
[right addObject:ip];
}
[_view.tableView beginUpdates];
[_view.tableView deleteRowsAtIndexPaths:[NSArray arrayWithArray:left]
withRowAnimation:UITableViewRowAnimationLeft];
[_view.tableView deleteRowsAtIndexPaths:[NSArray arrayWithArray:right]
withRowAnimation:UITableViewRowAnimationRight];
[_view.tableView endUpdates];
What happens now is that only the cells in view are removed and the rest pop in after the removal (also the issue seems to pop up since the dataSource only contains the rows that are in view for some reason). What i want is to remove all the rows. Any ideas?
The problem is in the for loop condition. The dataSource.count gets smaller each iteration. Try this:
for(int i=0;i<dataSource.count;i++){
NSIndexPath *ip = [NSIndexPath indexPathForRow:i inSection:0];
if(i%2==0)
[left addObject:ip];
else
[right addObject:ip];
}
[dataSource removeAllObjects];
try something like this:
[_view.tableView beginUpdates];
UITableViewRowAnimation animation;
for(int i = dataSource.count - 1; i>= 0; i--)
{
[dataSource removeObjectAtIndex: i];
NSIndexPath* ip = [NSIndexPath indexPathForRow: i
inSection: 0];
if(i % 2 == 0)
{
animation = UITableViewRowAnimationLeft;
}
else
{
animation = UITableViewRowAnimationRight;
}
[_view.tableView deleteRowsAtIndexPaths: #[ip]]
withRowAnimation: animation];
}
[_view.tableView endUpdates];
You can do this in easy way...
[dataSource removeAllObjects];
[_view.tableView reloadData];
i think that you can put your dataSource = #[]; and [self.tableview reloadData]; and remove all cell in your tableview
The matter is, I want to have a grouped table view, and when I click on a cell, I want to have an another cell to appear under it, and so on. Everything is fine with workflow, but I have same problems with animations. It works very slowly and I can see all changes
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"selected section:%d selected row:%d",indexPath.section,indexPath.row);
NSIndexPath* pathToDelete;
[_tableView beginUpdates];
if (_selectedPath != nil && [_selectedPath isEqual:indexPath]){
//If the same row was selected
pathToDelete = [NSIndexPath indexPathForRow:_selectedPath.row+1 inSection:_selectedPath.section];
_selectedPath = nil;
[_tableView beginUpdates];
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:pathToDelete] withRowAnimation:UITableViewRowAnimationTop];
[_tableView endUpdates];
} else {
//If not
if (_selectedPath != indexPath){
//delete the row that we selected last time
if (_selectedPath != nil){
pathToDelete = [NSIndexPath indexPathForRow:_selectedPath.row inSection:_selectedPath.section];
[_tableView beginUpdates];
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:pathToDelete] withRowAnimation:UITableViewRowAnimationTop];
[_tableView endUpdates];
}
//add new row in the section we selected
_selectedPath = indexPath;
[_tableView beginUpdates];
[_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[_tableView endUpdates];
}
}
[_tableView beginUpdates];
[_tableView deselectRowAtIndexPath:indexPath animated:NO];
[_tableView endUpdates];
[_tableView reloadSections:[[NSIndexSet alloc] initWithIndex:pathToDelete.section] withRowAnimation:UITableViewRowAnimationMiddle];
[_tableView reloadSections:[[NSIndexSet alloc] initWithIndex:_selectedPath.section] withRowAnimation:UITableViewRowAnimationMiddle];
[_tableView endUpdates];
}
I think the problem is with begin & endUpdates method, but I don't know where exactly. Any clue?
Thanks
You could do this much simpler, by using a single beginUpdates - endUpdates. You just make your deletions and insertions inside of it. Don`t forget to update the data source for the table, otherwise the app will crash.
Hope this helps!
The else part of this works fine. But if itemFlag is true, I can't get the new information to display itself correctly after doing the alphabetic sort. Quitting the programme and restarting shows the new item to have been added successfully to the array, and everything is diplayed correctly.
So my question is, why is reloadData not working if itemFlag is true?
Here is the code:
- (void)changeFoodDetails:(NSString *)foodName withPoints:(NSString *)foodPoints{
if (newItemFlag) {
[_foodStuffsArray insertObject:[[FoodItem alloc] initWithName:foodName points:[foodPoints intValue]] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[sharedManager sortFoodStuffArrayByName];
[self.tableView reloadData];
newItemFlag = false;
}else {
[_foodStuffsArray removeObjectAtIndex:currentFoodstuffArrayEntry];
[_foodStuffsArray insertObject:[[FoodItem alloc] initWithName:foodName points:[foodPoints intValue]] atIndex:currentFoodstuffArrayEntry];
[self.tableView reloadData];
}
}