MCKapur
MCKapur

Reputation: 9157

Objective-C NSMutableArray removeObjectAtIndex: crashes

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...

Upvotes: 1

Views: 2001

Answers (2)

Ramy Al Zuhouri
Ramy Al Zuhouri

Reputation: 21986

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];

Upvotes: 4

sunkehappy
sunkehappy

Reputation: 9101

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);
}

Upvotes: 1

Related Questions