1

I have a view controller with a table view where you can delete the cells. I have another class which handles things called bookmarks, the class is called BookmarkHandler. There are methods where you can upload a bookmark, get the whole bookmark array and delete a bookmark. Here is the class as follows:

+ (NSMutableArray *)bookmarkCollection {

NSMutableArray *bookmarkCollection = [[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"];

if (!bookmarkCollection) {

    bookmarkCollection = [[NSMutableArray alloc] init];
}

return bookmarkCollection;
}

+ (void)deleteBookmark: (NSIndexPath *)indexPath {

    NSMutableArray *bookmarkCollection = [[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"];

    [bookmarkCollection removeObjectAtIndex: indexPath.row];

    [[NSUserDefaults standardUserDefaults] setObject:bookmarkCollection forKey: @"bookmarks"];

    [[NSUserDefaults standardUserDefaults] synchronize];

}
+ (void)uploadBookmark:(NSDictionary *)singleBookmark {

    NSMutableArray *bookmarkCollection = [[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"];


if (!bookmarkCollection) {

    bookmarkCollection = [[NSMutableArray alloc] init];
} 

NSMutableDictionary *bookmark1 = [[NSMutableDictionary alloc] initWithDictionary: singleBookmark];

NSMutableDictionary *bookmark2 = [[NSMutableDictionary alloc] initWithDictionary: singleBookmark];


NSNumber *number1 = [[NSNumber alloc] initWithInt: 1];
NSNumber *number2 = [[NSNumber alloc] initWithInt: 2];

[bookmark1 setObject:number1 forKey: @"bookmarkTag"];
[bookmark2 setObject:number2 forKey: @"bookmarkTag"];

[bookmarkCollection addObject: bookmark1];
[bookmarkCollection addObject: bookmark2];

[[NSUserDefaults standardUserDefaults] setObject:bookmarkCollection forKey: @"bookmarks"];

[[NSUserDefaults standardUserDefaults] synchronize];

}

The bookmark collection which is a mutable array, is populated by dictionaries which have name and date objects/keys. These name and dates is what populates the table view cell title's in the other view controller. The number of cells in the table view is determined by the [[BookmarkHandler bookmarkCollection] count];

In the other view controller you can delete the table view cells, so what I do is I implement the delegate method:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {


if (editingStyle == UITableViewCellEditingStyleDelete) {

    [BookmarkHandler deleteBookmark: indexPath]; 

    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject: indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
}

So, when I delete a cell, I delete a bookmark from BookmarkHandler by calling the deleteBookmark: and delete the row from the table view. But sometimes there is a crash on this line:

        [bookmarkCollection removeObjectAtIndex: indexPath.row];

But there is no crash log, and I have added an All Exceptions breakpoint.

Is there something I am doing wrong? Thanks for help...

MCKapur
  • 9,127
  • 9
  • 58
  • 101

2 Answers2

4

The problem is here:

NSMutableArray *bookmarkCollection = [[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"];

NSUserDefaults doesn't save a mutable array, it just saves it as NSArray.
So take the mutable copy of it:

NSMutableArray *bookmarkCollection = [[[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"] mutableCopy];
Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
1

You should check the indexPath.row to make sure it is NOT out of boundry. After this maybe you can find the reason.

if (indexPath.row>=0 && indexPath.row<bookmarkCollection.count) {
    [bookmarkCollection removeObjectAtIndex: indexPath.row];
} else {
    NSLog(@"indexPath.row is out of boundry of bookmarkCellection size: %d", bookmarkCollection.count);
}
sunkehappy
  • 8,970
  • 5
  • 44
  • 65
  • I put that if statement, and only now am I getting this crash log: – MCKapur Sep 27 '12 at 01:11
  • 2012-09-27 09:10:25.829 MileIndex[35555:1d903] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object' – MCKapur Sep 27 '12 at 01:12
  • which says that I am removeObjectAtIndex: from an NSArray, but it is a mutable array... let me check my code if i accidentally set the bookmarkCollection to a non mutable nsarray object – MCKapur Sep 27 '12 at 01:13
  • Year, if you really have NOT set the bookmarkCollection to a non mutable NSArray, just new a NSMutableArray from the `[[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"]` – sunkehappy Sep 27 '12 at 01:15
  • I don't see an NSArray anywhere – MCKapur Sep 27 '12 at 01:24
  • Try `+ (NSMutableArray *)bookmarkCollection {
    NSMutableArray *bookmarkCollection = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey: @"bookmarks"]]; if (!bookmarkCollection) { bookmarkCollection = [[NSMutableArray alloc] init]; } }`
    – sunkehappy Sep 27 '12 at 01:31