Vanya
Vanya

Reputation: 5005

NSDictionary as property

I am getting memory leaks pointing to the line "NSDictionary *dw = [NSDictionary dictionaryWithContentsOfFile:path];" by using following code

NSDictionary    *_allData;

@property (nonatomic, retain) NSDictionary  *allData;

@synthesize allData = _allData;

+ (NSString*)getNSPath

{
 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

 NSString *documentsDirectory = [paths objectAtIndex:0];

 NSString *path = [documentsDirectory stringByAppendingPathComponent:@"alarm.plist"];

 return path;
}


- (NSDictionary *)allData
{
 NSString *path = [saveAlarm getNSPath];
 NSDictionary *dw = [NSDictionary dictionaryWithContentsOfFile:path];


 _allData = [NSDictionary dictionaryWithDictionary:dw];

    return _allData;
}

The data are changing in the pList and when I ask to retrieve what is new there by property then it leaks. Any recommendation how to make clear? Or how to implement this kind of thing without leaks?

Thanks

Upvotes: 0

Views: 3259

Answers (2)

Kris Markel
Kris Markel

Reputation: 12112

You need to release _allData before reassigning it. You also need to retain it when you assign it.

EDIT: Incorporating Robert's improvement to get rid of an unneeded NSDictionary.

EDIT2: Because you're returning an object across an API boundary, it need to be retuned as an autoreleased object.

- (NSDictionary *)allData
{
     NSString *path = [saveAlarm getNSPath];
     [_allData release];
     _allData = [[NSDictionary dictionaryWithContentsOfFile:path] retain];

    return [_allData autorelease];
}

The code you posted is a bit odd in that you're creating a property called allData, telling it to use _allData as the ivar (with @synthesize) and then implementing a custom getter that sets the ivar. If you declare the property as readonly, you can remove the @synthesize statement.

If you're only using _allData inside this method and not anywhere else in this class, you can get rid of it entirely. Here's a much simpler version that does the same thing:

- (NSDictionary *)allData
{
     NSString *path = [saveAlarm getNSPath];
     return [NSDictionary dictionaryWithContentsOfFile:path];
}

Upvotes: 2

Robert Redmond
Robert Redmond

Reputation: 1522

Why don't you replace

NSDictionary *dw = [NSDictionary dictionaryWithContentsOfFile:path];


_allData = [NSDictionary dictionaryWithDictionary:dw];

With

_allData = [NSDictionary dictionaryWithContentsOfFile:path];

Then you don't have to worry about the dw NSDictionary's autorelease which is probably causing your leak.

Upvotes: 0

Related Questions