ObjectiveC - освобождение объектов, добавленных в качестве параметров - PullRequest
0 голосов
/ 12 января 2011

Хорошо, вот и все.

Будучи Java-разработчиком, я все еще борюсь с управлением памятью в ObjectiveC. У меня есть все основы, но время от времени я сталкиваюсь с проблемой.

То, что я хочу сделать, это то, что в Java выглядело бы так:

MyObject myObject = new MyObject(new MyParameterObject());

Конструктор класса MyObject принимает параметр типа MyParameterObject, который я запускаю на лету.

В ObjectiveC я попытался сделать это, используя следующий код:

MyObject *myObject = [[MyObject alloc] init:[[MyParameterObject alloc] init]];

Однако, запустив инструмент Build and Analyze, я получаю предупреждение «Потенциальная утечка объекта» для объекта MyParameter, которое действительно возникает, когда я тестирую его с помощью инструментов. Я понимаю, почему это происходит, потому что я беру на себя владение объектом с помощью метода alloc и не отказываюсь от него, я просто не знаю, как правильно это сделать. Я пытался использовать

MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]];

но затем инструмент «Анализ» сказал мне, что «Объект отправлен -авто, слишком много раз».

Я мог бы решить эту проблему, изменив метод init на MyParameterObject, сказав return [self autorelease]; вместо return self;. Анализ все еще предупреждает о потенциальной утечке, но на самом деле это не происходит. Однако я считаю, что этот подход нарушает соглашение об управлении памятью в ObjectiveC, и я действительно хочу сделать это правильно.

Спасибо заранее.

Ответы [ 4 ]

3 голосов
/ 12 января 2011

Хорошо, вот предложение.

MyParameter *param = [[MyParam alloc] init];
MyObject *obj = [[MyObject alloc] initWithParam:param]; // do you know if param is retain'd or not?
[param release];

Почему это так?Это шаблон, используемый в ObjC / Cocoa.Вы добавляете объекты в NSArrays следующим образом:

MyThing *thing = [[MyThing alloc] init];
[myMutableArray addObject: thing]; // this calls [thing retain]
[thing release];

Вы также можете попытаться сделать это:

MyObject *obj = [[MyObject alloc] initWithParam: [MyParameter parameter]];

где:

+ (id) parameter
{
    return [[[self alloc] init] autorelease];
}    

таким образом выне нужно беспокоиться об этом.Это то же самое, что и

[NSData data];
[NSArray array];

Надеюсь, это поможет.Обычно не рекомендуется использовать init во время вызова другого метода (например, для установки или другого init).Скрытие его за методом класса (+ (id) parameter) означает, что пользователь знает, что это будет autorelease 'd.

Если вам когда-либо неясно, сколько retain или release'Если что-то есть, вы всегда можете сделать что-то вроде этого:


[РЕДАКТИРОВАТЬ]

Предупреждение: Очевидно, вы никогда не должны использовать -retainCount.Я считаю его полезным для обучения учащихся основам retain управления памятью, но суть хорошо принята.

Никогда не используйте его в реальном коде или для тестирования производительности. Это используется только для того, чтобы узнать, что делает retain (и я считаю, что в этом случае оно работает правильно).Он никогда не даст вам интеллектуальный ответ для объекта, который autorelease 'd или дальше retain' d NSArray или другими классами Foundation / AppKit / UIKit

MyParameter *param = [[MyParam alloc] init];
NSLog(@"param retain count: %d",[param retainCount]); // should be 1
MyObject *obj = [[MyObject alloc] initWithParam:param];
NSLog(@"param retain count: %d",[param retainCount]); // should be 2, if MyObject retains it.
[param release];
NSLog(@"param retain count: %d",[param retainCount]);  // should be 1

Кроме того, когда вы dealloc MyObject, вам потребуется release param, если вы retain сделали это во время инициализации.

Следующее руководство выпущеноApple должна помочь вам лучше понять управление памятью в Objective-C.

2 голосов
/ 12 января 2011
MyThing *thing = [[MyThing alloc] init];
[otherThing methodWithAThing:thing];
[thing release];

или:

[otherThing methodWithAThing:[[[MyThing alloc] init] autorelease]];

или (если в используемом классе есть «конструктор удобства»):

[otherThing methodWithAThing:[MyThing thing]];
0 голосов
/ 12 января 2011
[[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]]

Не зная, что происходит в методе init, это выглядит нормально.

Обратите внимание, что Objective-Cish лучше записать как "initWithParameterObject:"Хотя они описывают людей, плохо знакомых с языком, имена описательных методов Obj-C действительно очень полезны для удобства чтения кода.

0 голосов
/ 12 января 2011
MyObject *myObject = [[MyObject alloc] init:[[[MyParameterObject alloc] init] autorelease]];

должно быть в порядке, если в init нет релиза (в init не должно быть релиза). Я часто делаю метод класса, который создает объект с автоматическим освобождением. Таким образом, код будет:

// using it:
MyObject *myObject = [[MyObject alloc] init:[MyParameterObject defaultParameters];

// in the class implementation of MyParameterObject
+ (MyParameterObject*) defaultParameters{
    MyParameterObject* out = [[MyParameterObject alloc] init];
    // set some values
    return [out autorelease];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...