0

Hi

I want to delete items from a NSMutableArray through a UITableView but something crash the app. The crash is "0 objc_msgSend".

Here's my code guys:

- (void)viewDidLoad
{
    paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    path = [basePath stringByAppendingPathComponent:@"favoris.plist"];
    dict = [[NSArray arrayWithContentsOfFile:path] mutableCopy];
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

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

    [dict removeObjectAtIndex:indexPath.row];

    [self.tableView reloadData];
}

Thanks

user1269586
  • 372
  • 1
  • 6
  • 27
  • Hi, welcome to SO! In order for us to help you figure out what is wrong, it would be very helpful if you posted the error that it prints when your application crashes. – lnafziger Nov 10 '12 at 15:14
  • @lnafziger Well, excuse me man, I just updated my post ;) – user1269586 Nov 10 '12 at 15:16
  • No excuse needed. It would help even more if you posted the **entire** message that it prints. ;) – lnafziger Nov 10 '12 at 15:22
  • `[MyViewController tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath]` And there's a EXC_BAD_ACCESS on the line: `[dict removeObjectAtIndex:indexPath.row];` – user1269586 Nov 10 '12 at 15:26
  • Okay, that helps! Are you using ARC? – lnafziger Nov 10 '12 at 15:28
  • hmmm, i think that mutableCopy adds a retain? i'm deleting my dumb answer below. – danh Nov 10 '12 at 15:53
  • @lnafziger The NSLog isn't `nil`, if I put it in the `viewDidLoad` I see all my dictionary... – user1269586 Nov 10 '12 at 15:57
  • Yeah, that was my mistake. I've been using ARC too long, lol. – lnafziger Nov 10 '12 at 15:59
  • Okay, can you add the code that is populating the table view? (cellForRowAtIndexPath most likely.) – lnafziger Nov 10 '12 at 15:59
  • @lnafziger So you have not idea how can I solve this crash ? – user1269586 Nov 10 '12 at 16:01
  • Well, I'm still trying to help. That's why I asked for more code; in order to see how your data is being used by your table. – lnafziger Nov 10 '12 at 16:02
  • Also, can we see some log output from commitEditingStyle. Like, NSLog(@"array is %@", dict); and NSLog(@"removing index %d with count=%d", indexPath.row, dict.count); – danh Nov 10 '12 at 16:05
  • 1
    Also, as @Inafziger suggests, it sure does look like memory. Can you follow these instructions to look for zombies? http://stackoverflow.com/questions/5386160/how-to-enable-nszombie-in-xcode – danh Nov 10 '12 at 16:08
  • Okay so `NSLog(@"removing index %d with count=%d", indexPath.row, dict.count);` gimme `removing index 0 with count=2` the index is wrong but the count is good. (I forget to say that at the first time, the app doesn't crash, but if try to remove another item, then it crash) But if I quit the view after the first time and return on it, I can see that nothing was deleted... – user1269586 Nov 10 '12 at 16:15

1 Answers1

0

EXEC_BAD_ACCESS absolutely means there's a zombie, so I think there's some weirdness going on with your memory management, and it's probably happening due to how your instantiating the array. Running the Zombies tool in Instruments will absolutely give you more information, but here's something to try:

(another suggestion, why are you naming a variable for an NSArray as dict?).

Try this code:

- (void)viewDidLoad
{
    paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    path = [[basePath stringByAppendingPathComponent:@"favoris.plist"] retain];
    dict = [[NSMutableArray alloc] initWithContentsOfFile:path];
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    [dict removeObjectAtIndex:indexPath.row];
    [dict writeToFile:path atomically:YES]; 
    [self.tableView reloadData];
}

The basis for this suggestion is that I'm suspecting that calling copy on an autoreleased object will have unexpected consequences.

Andy Obusek
  • 12,614
  • 4
  • 41
  • 62
  • Thanks you, So now my code is in my `tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath` is: `dict = [[NSMutableArray alloc] initWithContentsOfFile:path]; [dict removeObjectAtIndex:indexPath.row]; [dict writeToFile:path atomically:YES]; [self.tableView reloadData];` It remove correctly the item at the first time but crash with a `EXEC_BAD_ACCESS` on the line: `[dict removeObjectAtIndex:indexPath.row];` – user1269586 Nov 10 '12 at 16:26
  • I think you put it in the wrong place. The code change I suggested goes in `viewDidLoad` not `commitEditingStyle` I updated my answer with the full example for you to try – Andy Obusek Nov 10 '12 at 16:33
  • 1
    @obuseme There is no difference between those two lines of code. The end result is a retained, mutable array. – rmaddy Nov 10 '12 at 16:34
  • Of course there is a difference. In the original code the `mutableCopy` command is calling retain on an object in the autorelease pool. My example removes the use of autorelease (that happens via the convenience constructor `arrayWithContentsOfFile`) – Andy Obusek Nov 10 '12 at 16:37
  • Yes but if I put it in the `viewDidLoad` I'll not have the `indexPath.row` – user1269586 Nov 10 '12 at 16:44
  • I updated my answer with an entire section of code for you to try. There is no reference to `indexPath.row` in `viewDidLoad` – Andy Obusek Nov 10 '12 at 16:45
  • The app crash, in the log I can read: `-[NSPathStore2 getFileSystemRepresentation:maxLength:]: message sent to deallocated instance 0xb588ae0` and there's `0 ____forwarding___` and `EXC_BREAKPOINT`. Do you understand why ? – user1269586 Nov 10 '12 at 16:53
  • The variable `path` is also getting deallocated at some point after `viewDidLoad` completes since it is not explicitly retained. Add a call to `retain` when you create the full path string. See my example: `path = [[basePath stringByAppendingPathComponent:@"favoris.plist"] retain];` – Andy Obusek Nov 10 '12 at 17:01
  • Well excuse me. App crash again with `0 objc_msgSend` and `EXC_BAD_ACCESS` on the line: `[dict removeObjectAtIndex:indexPath.row];` – user1269586 Nov 10 '12 at 17:04
  • Is your viewDidLoad method exactly as I have it in my answer? – Andy Obusek Nov 10 '12 at 17:15
  • Humm, maybe I got it (with new method: (`onButtonTapped:(UIButton *)button`) : `UITableViewCell *cell = (UITableViewCell *)button.superview.superview; NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; [dict removeObjectAtIndex:indexPath.row]; [dict writeToFile:path atomically:YES]; [self.tableView reloadData];`. The only and last problem is that it always delete indexPath.row == 0. Any idea? – user1269586 Nov 10 '12 at 17:30