Objective C Leaks memory on Autoreleased Object
Ok so I know there are a bunch of questions asked on this issue but after reading them and trying the methods out, my app still seems to leak memory. I have studied the Apple Guide on Memory Manegment and read notable questions here, here and here. I have a method that parses a JSON string and then returns the them into a NSMutableDictionary
. I call autorelease
on the object from the returning method and then call retain
on the receiving method (ensuring that the object is not dealloc on the next drain of the pool). Then I release then object when I am done with it. However it still leaks. Can anyone see what I am doing wrong?
Return Method
+ (NSMutableArray *)parseSpecialtyResult:(NSString *)json
{
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *dictionary = [parser objectWithString:json];
NSArray *jsonObjects = [dictionary valueForKey:@"Rows"];
NSMutableArray *jsonArray = [[NSMutableArray alloc] initWithCapacity:[jsonObjects count]];
//Storing objects
for (NSDictionary *dict in jsonObjects)
{
Specialty *specialty = [[Specialty alloc] init];
[specialty setName:[dict objectForKey:@"name"]];
[specialty setIdenity:[dict objectForKey:@"id"]];
开发者_Python百科[jsonArray addObject:specialty];
}
[parser release];
//Relinquish ownership of this object
return [jsonArray autorelease];
}
Calling Class
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
//This class will take the responsibility of the object's ownership
self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
[tableView reloadData];
[responseString release];
}
- (void)dealloc
{
[super dealloc];
//No longer need the object
[jsonArray release];
NSLog(@"Ref count %i", [jsonArray retainCount]);
}
Log
Ref count 1
You don't release the Speciality
objects in the for
statement:
for (NSDictionary *dict in jsonObjects)
{
Specialty *specialty = [[Specialty alloc] init];
...
[jsonArray addObject:specialty];
[specialty release];
}
Also, if jsonArray
is a retain or copy property, this over-retains the object:
self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
It should be simply (again, if retain or copy):
self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];
Also, [super dealloc];
should be the last statement in dealloc
.
Assuming jsonArray
is a retain
property of the calling class, you're adding an extra retain:
self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
^
Right here!
The setter should already be properly retaining and releasing. So that retain there just leaks the object.
The other answers are also correct that you need to release the Specialty objects. But the leak will remain either way as long as you're overretaining the array that the Specialty objects are in.
You are leaking on this line:
Specialty *specialty = [[Specialty alloc] init];
You create a bunch of specialities but you never release them.
And on this line you are overretaining the object jsonArray by using self in front.
self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
Because you probably declared your jsonArray property like:
@property(nonatomic,retain)...
and then you synthezied it. It created a setter for you that retains an object when you assing it using self.
so
self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];
is enough.
When you take owner ship of the object here, you might be getting two retain messages.
//This class will take the responsibility of the object's ownership
self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
if the jsonArray property is declared as (retain) or (nonatomic, retain). simply assigning the jsonArray to the property will cause a retain to be sent. You can change your code to:
> @property (nonatomic, retain) NSMutableArray *jsonArray;
>
> @synthesize jsonArray;
>
> self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];
精彩评论