开发者

Objective C Leaks memory on Autoreleased Object

开发者 https://www.devze.com 2023-03-24 10:42 出处:网络
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

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 forstatement:

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];
0

精彩评论

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