views:

31

answers:

1

I hate asking memory management questions - all the good answers are variations on RTFM. But this one is stumping me.

I have a (relatively) complex dictionary in my model class, where each key points to an array of arrays. I constantly add and delete items to it, depending on state. Each "item" is an array.

- (void)addToDictionary:(NSNumber *)itemID {

        // get what we need (associated array of arrays & key) from the incoming ID
        NSArray *incomingArray = [self getArrayFromID:[itemID intValue]];
        NSString *myKey = [incomingArray objectAtIndex:0];

        NSMutableArray *myNewArray = [[NSMutableArray alloc] init];

        // case 1: this key is not in the dictionary yet
        if ([[myDict allKeys] containsObject:myKey] == NO) {
            [myNewArray addObject:incomingArray];
            [myDict setObject:myNewArray forKey:myKey];

        // case 2: key already there; add new array to its array
        } else {
            myNewArray = [NSMutableArray arrayWithArray:[myDict objectForKey:myKey]];
            [myNewArray addObject:incomingArray];
            [myDict removeObjectForKey:myKey];
            [myDict setObject:myNewArray forKey:myKey];
        }
        // why isn't this line working??
        [myNewArray release];
}

My question is the last line. I allocated this array to help me work with the dictionary, and now I don't need it any more. But the program will crash if I release it, and work just fine if I comment that line out. What am I missing? TIA

+1  A: 

In case two you don't own the returned array. So only release it in case 1. And don't create something you'll not use. The NSMutableArray pointer will get assigned to some other data in case 2, not the one you've allocated. So you can't release something you don't own.

- (void)addToDictionary:(NSNumber *)itemID {
    NSArray *incomingArray = [self getArrayFromID:[itemID intValue]];
    NSString *myKey = [incomingArray objectAtIndex:0];

    NSMutableArray *myNewArray;

    if ([[myDict allKeys] containsObject:myKey] == NO) {
        // Create when you need it
        myNewArray = [[NSMutableArray alloc] init];
        [myNewArray addObject:incomingArray];
        [myDict setObject:myNewArray forKey:myKey];

        // release when you're done with it
        [myNewArray release];

    } else {
        myNewArray = [NSMutableArray arrayWithArray:[myDict objectForKey:myKey]]; // you don't own it!
        [myNewArray addObject:incomingArray];
        [myDict removeObjectForKey:myKey];
        [myDict setObject:myNewArray forKey:myKey];
    }
    // why isn't this line working??
    //[myNewArray release];
    // because in case 2 it's not pointing to the right memory
}

Hope it works, ief2

Ief2
thanks, ief2. That definitely works, and really helped me to understand why I was doing it wrong before.