Getting NSInvalidArgumentsException when deleting uitableviewcells - ios

I implemented the commitEditingStyle method to delete a row from my tableview. If I simply put [timersArray removeObjectAtIndex:indexPath.row] the row deletes just fine. The only problem is that it does not animate so I tried putting this:
[self->tableView beginUpdates];
[self->tableView deleteRowsAtIndexPaths:timersArray withRowAnimation:UITableViewRowAnimationBottom];
[self->tableView endUpdates];
but when I try and delete something it brings up this:
'NSInvalidArgumentException', reason: '-[Timer row]: unrecognized selector sent to instance 0x17ed37b0'
I thought it was because the timersArray is a NSMuttableArray and not a NSArray but that did not change anything. Can someone help me find out how to fix this? Anything will help. Thanks!

I fixed the issue by adding [NSArray arrayWithObject:indexPath] in place of timersArray in order for that to work I had to place the [timersArray removeRowAtIndex:indexPath.row] above the [self->tableView beginUpdates] and at that point it worked!

Related

UITableView crash if I delete rows too fast

I have an app with a UITableView which can delete cells using a row action. However, if I do two in quick succession, the app crashes with a BAD_EXEC.
The problem is clearly timing related. I'm asking the table to do something else before it's quite finished with the old. It could be the animations or it could be the removal of cells.
Either way, calling reloadData on the tableview before I start seems to fix it. There are two problems with this solution.
Firstly, reloadData interferes with some of the niceness of the usual row removal animations. It's no biggie but I'd prefer it with all animations intact.
Secondly, I still don't fully understand what's happening.
Can any one help me understand and/or suggest a better solution?
Here's the code...
-(void) rowActionPressedInIndexPath: (NSIndexPath *)indexPath timing:(Timing) doTaskWhen
{
[self.tableView reloadData]; // This is my current solution
[self.tableView beginUpdates];
ToDoTask *toDo = [self removeTaskFromTableViewAtIndexPath:indexPath];
toDo.timing = doTaskWhen; // Just some data model updating. Has no effect on anything else here.
[self.tableView endUpdates];
}
removeTaskFromTableView is mostly code to work out if I need to delete an entire section or a row. I've confirmed the app makes the right choice and the bug works either way so the only relevant line from the method is...
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
Edit: I have noticed that the standard delete row action provided by the system does not allow me to move that fast. There is an in-built delay which (presumably) prevents this exact problem.
-(void) rowActionPressedInIndexPath: (NSIndexPath *)indexPath timing:(Timing) doTaskWhen
{
// [self.tableView reloadData]; // This is my current solution
[self.tableView beginUpdates];
ToDoTask *toDo = [self removeTaskFromTableViewAtIndexPath:indexPath];
toDo.timing = doTaskWhen; // Just some data model updating. Has no effect on anything else here.
[self.tableView endUpdates];
}
Or try to reload table view in main thread.

Assertion failure in -[UITableView _endCellAnimationsWithContext:

I'm an amateur at best, and stuck on this error! surely something simple...
- (void)addTapped:(id)sender {
TechToolboxDoc *newDoc = [[TechToolboxDoc alloc] initWithTitle:#"New Item" thumbImage:nil fullImage:nil];
[_itemArray addObject:newDoc];
//[self.tableView beginUpdates];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_itemArray.count-1 inSection:0];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
NSLog(#"%#",indexPath);
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:YES];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionMiddle];
[self performSegueWithIdentifier:#"MySegue" sender:self];
//[self.tableView endUpdates];
it is breaking on the line the says
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:YES];
You need to add [UITableView beginUpdates] and [UITableView endUpdates] around:
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:YES];
From the class reference:
Note the behavior of this method when it is called in an animation
block defined by the beginUpdates and endUpdates methods. UITableView
defers any insertions of rows or sections until after it has handled
the deletions of rows or sections. This happens regardless of ordering
of the insertion and deletion method calls. This is unlike inserting
or removing an item in a mutable array, where the operation can affect
the array index used for the successive insertion or removal
operation. For more on this subject, see Batch Insertion, Deletion,
and Reloading of Rows and Sections in Table View Programming Guide for
iOS.
I think you are inserting the row in your tableView but not updating the number of rows at section that's why you are getting error in this line. So along with inserting the row You should also increase the array count or whatever you are using to show the number of rows in table view.
In my case, I was using Parse and I deleted a few users (one of which was my iPhone simulator). I got this error whenever refreshing the tableView.
I just deleted the app from the Simulator and made a new account and it works flawlessly.
#droppy's answer helped give me the lightbulb moment of what was wrong!
Hope that helps someone.

select table row don't work, if element out of view

If the app starts, I need to select table row of the last element, that was used.
The name of the last used element I save in plist.
The code I used is:
id plist = [[PlistHandler alloc] init];// FIXME: Dont work with long list, if the element is out of view.
if ([tableData containsObject:[plist readDataForKey:#"selectedFile"]]) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[tableData indexOfObject:[plist readDataForKey:#"selectedFile"]] inSection:0];
[self.fileTable selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
[self tableView:self.fileTable didSelectRowAtIndexPath:indexPath];
}
The problem I found is: If the row is out of view ( table is big and the element if lower then view), I get some exception: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: selectedFile)' Maybe someone know the better way to select a row or to work around.
UPDATE:
I debuged a bit and now I know where the issue happen:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
id plist = [[PlistHandler alloc] init];
[plist writeDataToKey:#"path" andData:[NSString stringWithFormat:#"%#/%#", documentsDirectory, cellText]];
[plist writeDataToKey:#"selectedFile" andData:cellText];
}
It's on the last line, because the cellText is nil, so maybe the index is wrong.
Bit why it works with the elements, that are in the view.
Cell is probably not initialized, because it has not be used. This is, because it is not on the screen.
The deeper problem is that you try to get data from the UI. The UI is for displaying data, not for storing and retrieving data. Retrieve the data from your model. Your application should know how to do this, because it knows how to set the cell.
https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/MVC.html

Terminating with uncaught exception of type NSException when deleting row from UITableView

I'm working on an app that will update and add user's coordinate to a UITableView when the user has traveled over a preset distance interval. The coordinates will be automatically added to an NSMutableArray, and I use the array to update the table.
Everything load up and work fine (I can edit the table by moving and re-ordering the rows) but whenever I chose to delete a specific row, the program crash with the error "libc++abi.dylib: terminating with uncaught exception of type NSException".
- (void) tableView:( UITableView *) tableView commitEditingStyle:( UITableViewCellEditingStyle) editingStyle forRowAtIndexPath:( NSIndexPath *) indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSArray *items = [[G5SharedStore sharedStore]allCoords];
G5SharedStore *item = items[indexPath.row];
[[G5SharedStore sharedStore]removeItem:item];
//THIS IS WHERE THE ERROR OCCURS
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
The last line is what causes the error, but I'm new to objective-c, so I'm not sure how to fix this. Any help would be appreciated. Let me know if you need more details.
Thanks in advance.
**Edit:
Ok, I played around with the code this morning and it works. The problem is that the array keeps adding more and more items, but the tableview doesn't, unless I go back out and click "show table" button again to refresh it. So whenever I delete something in the tableview, the table's size is inconsistent with the array's size therefore I get the error. Here's my new problem, I tried to solve the above problem by making the table automatically update its data using:
[tableView reloadData];
The table does update, but it keeps adding blank cells ... with no data in it. Here's where I added the above:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#" UITableViewCell"
forIndexPath:indexPath];
NSArray *items = [[G5SharedStore sharedStore] allCoords];
G5SharedStore *item = items[indexPath.row];
cell.textLabel.text = [item description];
[tableView reloadData];
return cell;
}
Since I just started iOS programming 1 month ago, I could be wrong. So please guide me.
Thanks again everyone
I can see two problems:
Firstly this article recommends modifying the table view before the data-model (you are doing it the other way round):
It must do two things:
Send deleteRowsAtIndexPaths:withRowAnimation: or insertRowsAtIndexPaths:withRowAnimation: to the table view to direct
it to adjust its presentation.
Update the corresponding data-model array by either deleting the referenced item from the array or adding an item to the array.
Secondly you don't appear to be calling beginUpdates and endUpdates around that call. To quote the reference:
Note the behavior of this method when it is called in an animation
block defined by the beginUpdates and endUpdates methods.
Instead of delete row delete object from the array and reload table
- (void) tableView:( UITableView *) tableView commitEditingStyle:( UITableViewCellEditingStyle) editingStyle forRowAtIndexPath:( NSIndexPath *) indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSArray *items = [[G5SharedStore sharedStore]allCoords];
G5SharedStore *item = items[indexPath.row];
[[G5SharedStore sharedStore]removeItem:item];
//Remove this
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
//Add This Line
[tableView reloadData];
}
}

UICollectionView crash when deleting last item

I am trying to update the uicollection view whenever I delete a item. All the cells are deleting fine but if I delete the last cell in that collection view App crashes and I have put
[self.collectionview performBatchUpdates:^{
[postarray removeObjectAtIndex:indexPath.item];
[self.collectionview deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row inSection:1]]];
} completion:^(BOOL finished) {}];
The error I got is 'NSRangeException', reason: '* -[__NSArrayI objectAtIndex:]: index 17 beyond bounds [0 .. 16]' . Even array and collection view item starts at same index,I got this message
I was getting the same error message with the same lines of code, and it turned out it had nothing to do with the UICollectionView data source, but with a parallel array in another part of the app that updated its contents after but not its active index after the delete.
To find errors like this, enable Exception breakpoints: NSRangeException when deleting last UICollectionViewCell
Just inverse your two lines. You need to remove cell before to remove your object.
[self.collectionview performBatchUpdates:^{
[self.collectionview deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexPath.row inSection:1]]];
[postarray removeObjectAtIndex:indexPath.item];
} completion:^(BOOL finished) {}];

Resources