NSInternalInconsistencyException while deleting/inserting rows in UITableView - uitableview

I need to create an app with tableView. For now I can just load/reload all data in my table. To add/delete operation tableView has editing mode. But the problem is that in this mode tableView shows standart add/delete buttons. But I don't need this buttons. In Apple tutorial I found other way to do add/delete row like this:
[data removeObjectAtIndex:0];
[data addObject:[[chooseTypeCell alloc]init]];
NSIndexPath *insertIndexPaths=[NSIndexPath indexPathForRow:[data count] inSection:0];
NSIndexPath *deleteIndexPaths=[NSIndexPath indexPathForRow:0 inSection:0];
[[self view] beginUpdates];
[[self view] insertRowsAtIndexPaths:[NSArray arrayWithObject:insertIndexPaths] withRowAnimation:UITableViewRowAnimationRight];
[[self view] deleteRowsAtIndexPaths:[NSArray arrayWithObject:deleteIndexPaths] withRowAnimation:UITableViewRowAnimationFade];
[[self view] endUpdates];
But it causes an error =(.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid table view update. The application has requested an update to the table view that is inconsistent with the state provided by the data source.'
In my case I'm using object, which is subclass of UITableViewController, with UITableViewdataSource and UITableViewDelegate protocols. In this object the view variable is connected with my UITableView. As a result, UITableView connects with the only it's controller. In this controller I defined these methods:
#pragma mark - Table view data source
#######>>>>> right code =)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
#######>>>>> in comment section
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
#######>>>>> without any code or cap
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
#pragma mark - Table view delegate
#######>>>>> right code =)
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
#######>>>>> in comment section
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
#######>>>>> without any code or cap
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath
*)indexPath
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath
*)indexPath
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath
*)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Any ideas what's wrong?

Error like this:
Assertion failure in -[_UITableViewUpdateSupport _computeRowUpdates], /SourceCache/UIKit/UIKit-1912.3/UITableViewSupport.m:386
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid table view
update. The application has requested an update to the table view
that is inconsistent with the state provided by the data source.'
May appear because your UITable-Data class is wrong defined.
You need to pay your attention to this methods:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Also you need to check your animation code. All indexes must be taken from result data structure.
In Apple Documentation:
Deletion and reloading operations within an animation block specify
which rows and sections in the original table should be removed or
reloaded; insertions specify which rows and sections should be added
to the resulting table. The index paths used to identify sections and
rows follow this model. Inserting or removing an item in a mutable
array, on the other hand, may affect the array index used for the
successive insertion or removal operation; for example, if you insert
an item at a certain index, the indexes of all subsequent items in the
array are incremented.
In my case: error arises in insertRowsAtIndexPaths function. Because all my changes (in my data) were applied by the time of execution. And new position of my UITableViewCell was ([data count]-1) meanwhile I used just [data count].
Thanks for your attention =).

Related

How to dynamic cell height with Parse?

Here is my storyboard:
The method i use to get the image is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
cell.mainImage.file = (PFFile *)object[#"image"];
[cell.mainImage loadInBackground];
}
Row Height is set as:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 501.0f;
}
I also would like to have the Image to be filled perfectly, much like instagram. I dont want images to have bars on the top and bottom.
this was work for me
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}

Reorder tableview cell with a custom button

I'm developing an application an I have a UITableView, I am using the following code to manage reordering:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
-(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{
if(proposedDestinationIndexPath.section==0 && proposedDestinationIndexPath!=sourceIndexPath){
return proposedDestinationIndexPath;
}
else{
return sourceIndexPath;
}
}
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
//move rows
}
it works fine, but I want to change the Reorder button position and implement something like Music queue list on iOS 8.4.
I want to change the reorder button to be on the scrollview which contents of the cell are and move with the cell.
Screenshot:
Thanks in advance :)
According to this tutorial you can set UITableViewCellReorderControl as a part of UITableViewCellContentView so it will move with the cell's content:
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIView *reorderControl = [cell huntedSubviewWithClassName:#"UITableViewCellReorderControl"];
UIView *contentView = [cell huntedSubviewWithClassName:#"UITableViewCellContentView"];
UIView *resizedGripView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(reorderControl.frame), CGRectGetMaxY(reorderControl.frame))];
[resizedGripView addSubview:reorderControl];
[contentView addSubview:resizedGripView];
// Original transform
CGAffineTransform transform = CGAffineTransformIdentity;
// Move reorderControl to the left with an arbitrary value
transform = CGAffineTransformTranslate(transform, -100, 0);
[resizedGripView setTransform:transform];
}
I solved my problem using the code here for reordering and then I used UITableView delegates as follow for swipe to delete.
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleDelete;
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
//Remove selected cell from tableview and you data source
}
}

When I am moving cells in UITableView, I can only drag last but one cell to only last position

I have a problem with my UITableViewController. I have list of objects that I want to move.
The thing is that I am able only to move the last of one cell to the last position, not any other of cells. I think it is just simple code, but I really do not know, what I am missing.
I do not want to delete or insert objects, I just want to move them. Thanks for any help.
Here is my code:
myListOfObjects is NSMutableArray of my custom objects
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerCellClassWithNib:[MyCustomCell class]];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.tableView setEditing:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.myListOfObjects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:[MyCustomCell className]
forIndexPath:indexPath];
cell.myObject = self.myListOfObjects[indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
[self.myListOfObjects exchangeObjectAtIndex:toIndexPath.row withObjectAtIndex:fromIndexPath.row];
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
Why not use remove and insert objects in self.myListOfObjects. All examples that I saw about tableView:moveRowAtIndexPath use this approach.
Just try:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
MyObject *myObject = [self.myListOfObjects objectAtIndex:fromIndexPath.row];
[self.myListOfObjects removeObject:myObject];
[self.myListOfObjects insertObject:myObject atIndex:toIndexPath.row];
}
Instead of:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
[self.myListOfObjects exchangeObjectAtIndex:toIndexPath.row withObjectAtIndex:fromIndexPath.row];
}
Try to use following TableView DataSource method for editing:
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath {
/**
Add your condition here if any
*/
// Allow the proposed destination.
return proposedDestinationIndexPath;
}
And Exchange your objects in following delegate method:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
/**
Exchange the index of two objects
*/
[self.YourDataObjectArr exchangeObjectAtIndex:toIndexPath.row withObjectAtIndex:fromIndexPath.row];
}

Remove text of uitableviewcell when you are delegating two uitableview

I have a uitableviewdelegate class that is delegate of two uitableview. I want that one of them has remove button and the other do not have remove button. I used below code:
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
if(tableView==self.firstTableView){
return #"Remove";
}else
return #"";
}
button my code do not disable editing style for secondTableView it just set empty text as title. How can I do this?
EDIT
I also use below methods:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView == slef.FirstTableView){
//Some codes
}
}
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView == self.FirstTableView){
//Some codes
}
}
but any of them was not helpful.
Please implement this delegate method.
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView==self.firstTableView) {
return NO;
}
return YES;
}
Use delegate method
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
Here you can return UITableViewCellEditingStyleNone or UITableViewCellEditingStyleDelete for desired table

UITableView editing style may not show delete button

Occasionally, when UITableView is in editing style and when you trigger the delete button, this button may not show. It seldom happen, but did anybody get the same issue too?
Post some code:
In viewDidLoad,
[[self tableView] setEditing:YES animated:YES];
table view delegate:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
//do sth.
}
}

Resources