Objective C Утечки памяти на Авто-выпущенном Объекте - PullRequest
0 голосов
/ 30 июля 2011

Хорошо, я знаю, что по этому вопросу задано множество вопросов, но после их прочтения и опробования методов мое приложение все еще испытывает утечку памяти.Я изучил Руководство Apple по управлению памятью и прочитал заметные вопросы здесь , здесь и здесь .У меня есть метод, который анализирует строку JSON, а затем возвращает их в NSMutableDictionary.Я вызываю autorelease для объекта из возвращаемого метода, а затем вызываю retain для принимающего метода (гарантируя, что объект не будет освобожден при следующем сливе пула).Затем я освобождаю объект, когда я закончу с ним.Однако это все еще протекает.Кто-нибудь может увидеть, что я делаю не так?

Метод возврата

+ (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"]];

        [jsonArray addObject:specialty];
    }

    [parser release];

    //Relinquish ownership of this object
    return [jsonArray autorelease];
}

Класс вызова

- (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]);
}

Журнал

Ref count 1

Ответы [ 4 ]

5 голосов
/ 30 июля 2011

Вы не освобождаете объекты Speciality в операторе for:

for (NSDictionary *dict in jsonObjects) 
{
    Specialty *specialty = [[Specialty alloc] init];
    ...
    [jsonArray addObject:specialty];
    [specialty release];
}

Кроме того, если jsonArray является свойством сохранения или копирования, это приводит к чрезмерному сохранению объекта:

self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];

Это должно быть просто (опять же, если сохранить или скопировать):

self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];

Кроме того, [super dealloc]; должно быть последним оператором в dealloc.

3 голосов
/ 30 июля 2011

Предполагая, что jsonArray является свойством retain вызывающего класса, вы добавляете дополнительное сохранение:

self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];
                                                                        ^ 
                                                                   Right here!

Сеттер уже должен правильно удерживать и отпускать. Так что удерживать там просто протекает объект.

Другие ответы также верны, что вам нужно освободить объекты Specialty. Но утечка останется в любом случае, если вы перегрузите массив, в котором находятся объекты Specialty.

0 голосов
/ 30 июля 2011

Когда вы принимаете владелец объекта здесь, вы можете получить два сообщения об удержании.

 //This class will take the responsibility of the object's ownership
 self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];

если свойство jsonArray объявлено как (сохранить) или (неатомное, сохранить). простое назначение jsonArray для свойства приведет к отправке сохранения. Вы можете изменить свой код на:

> @property (nonatomic, retain) NSMutableArray  *jsonArray;
> 
> @synthesize jsonArray;
> 
> self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];
0 голосов
/ 30 июля 2011

Вы просачиваетесь по этой линии:

Specialty *specialty = [[Specialty alloc] init];

Вы создаете кучу блюд, но никогда не выпускаете их.

И в этой строке вы переопределяете объект jsonArray, используя self впереди.

self.jsonArray = [[SpecialtyUrl parseSpecialtyResult:responseString] retain];

Поскольку вы, вероятно, объявили свое свойство jsonArray следующим образом:

@property(nonatomic,retain)...

и затем вы синтезировали его. Он создал для вас сеттер, который сохраняет объект, когда вы используете его с помощью self.

так

self.jsonArray = [SpecialtyUrl parseSpecialtyResult:responseString];

достаточно.

...