开发者

Releasing NSArray containing NSDictionary objects

开发者 https://www.devze.com 2022-12-18 01:39 出处:网络
I am having difficulty getting my head around memory management in the following segment of code on iPhone SDK 3.1.

I am having difficulty getting my head around memory management in the following segment of code on iPhone SDK 3.1.

// Create array to hold each PersonClass object created below
NSMutableArray *arrayToReturn = [[[NSMutableArray alloc] init] autorelease];

NSArray *arrayOfDictionaries = [self generateDictionaryOfPeople];

[arrayOfDictionaries retain];

for (NSDictionary *dictionary in arrayOfDictionaries) {

    PersonClass *aPerson = [[PersonClass alloc] init];

    for (NSString *key in [dictionary keyEnumerator]) {

        if ([key isEqualToString:[[NSString alloc] initWithString: @"FIRST_NAME"]])
            aPerson.firstName = [dictionary objectForKey:key];

        else if ([key isEqualToString:[[NSString alloc] initWithString: @"LAST_NAME"]])
            aPerson.lastName = [dictionary objectForKey:key];

    }

    // Add the PersonClass object to the arrayToReturn array
    [arrayToReturn addObject: aPerson];

    // Release the PersonClass object
    [aPerson release];

}

return arrayToReturn;

The [self generateDictionaryOfPeople] method returns an array of NSDictionary objects. Each NSDictionary object has two keys "FIRST_NAME" and "LAST_NAME" with a person's first name and last name as the respective data. The code is looping through each dictionary object in the arrayOfDictionaries array and assigning the dictionary data to the relevant property of an aPerson (PersonClass) object. This object is then added to an array which is returned from this method.

When running instruments I am getting a leak for the dictionary objects contained in the arrayOfDictionaries array. The code within the [self generateDictionaryOfPeople] method is calling [dictionaryObject release] on each NSDictionary object as it is created and added to the array, which makes the retain count on the object 1 (as adding the object to the array would make the retain count 2, but then my release message decrements it back to 1).

I assume this leak is because I am never releasing the arrayOfDictionaries array, 开发者_如何学编程and thus the NSDictionary objects within the array are never released. If I attempt to release the array at the end of the above segment of code I get a "message sent to deallocated instance" error. I understand why this is occurring, because I am assigning the aPerson object data within a dictionary item (that I am subsequently releasing) but I don't know where else I can release the arrayOfDictionaries array. Any help would be greatly appreciated.

Thanks!

EDIT: Below is the implementation for [self generateDictionaryOfPeople]

- (NSArray *)generateDictionaryOfPeople {

    NSMutableArray *arrayFromDatabase = [[[NSMutableArray alloc] init] autorelease];

    // ** Query the database for data **

    while ( there are rows being returned from the database ) {

        // Declare an NSMutableDictionary object
        NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];

        // Loop through each column for that row
        for ( while there are columns for this row ) {

            columnTitle = title_of_column_from_database
            columnData = data_in_that_column_from_database

            // Add to the dictionary object
            [dictionary setObject:columnData forKey:columnTitle];

            // Release objects
            [columnName release];
            [columnTitle release];

        }

        // Add the NSMutableDictionary object to the array
        [arrayFromDatabase addObject:dictionary];

        // Release objects
        [dictionary release];

    }

    // Return the array
    return arrayFromDatabase;

}


Here,

    if ([key isEqualToString:[[NSString alloc] initWithString: @"FIRST_NAME"]])
        aPerson.firstName = [dictionary objectForKey:key];

    else if ([key isEqualToString:[[NSString alloc] initWithString: @"LAST_NAME"]])
        aPerson.lastName = [dictionary objectForKey:key];

Replace them with

    if ([key isEqualToString:@"FIRST_NAME"])
        aPerson.firstName = [dictionary objectForKey:key];

    else if ([key isEqualToString:@"LAST_NAME"])
        aPerson.lastName = [dictionary objectForKey:key];

The problem of the leak is you're creating 1 ~ 2 NSString-s per loop without -release-ing them. If you need constant NSString-s, just directly use them.


I am still getting the original leak due to not releasing the arrayOfDictionaries array.

That means you forgot to autorelease it in generateDictionaryOfPeople.

You need to review the memory management rules.


You are not releasing arrayFromDatabase. (The simplest way to avoid this kind of mistake is to use factories and autorelease as early as possible rather than defer releases manually. In this case, use [NSMutableDictionary dictionary] instead of [[NSMutableDictionary alloc] init].)

0

精彩评论

暂无评论...
验证码 换一张
取 消