Зачем вызывать autorelease для определения iVar в методе init? - PullRequest
2 голосов
/ 30 апреля 2010

Я просто ознакомился с CLLocationManager и нашел несколько примеров определений классов, которые содержат следующий метод init:

- (id) init {
    self = [super init];

    if (self != nil) {
        self.locationManager = [[[CLLocationManager alloc] init] autorelease];
        self.locationManager.delegate = self;
    }
    return self;
}

- (void)dealloc {
    [self.locationManager release];
    [super dealloc];
}

Я не понимаю, почему iVar будет выпущен автоматически. Не означает ли это, что он освобождается в конце метода init?

Я также озадачен тем, что в тех же примерах кода есть версия iVar в методе dealloc.

Есть мысли? «

Ответы [ 3 ]

6 голосов
/ 30 апреля 2010

locationManager - это свойство, которое, вероятно, установлено с атрибутом retain.

В основном, если вы только напишите:

self.locationManager = [[CLLocationManager alloc] init];

установщик левой стороны self.locationManager сохраняет ссылку на выделенную CLLocationManager. Но правая ссылка CLLocationManager сама по себе никогда не выпускается. Число сохранений для этого менеджера никогда не достигает нуля, и объект никогда не исчезает - это вызывает утечку памяти.

Есть два способа решения этой проблемы. Либо autorelease выделенный объект, как вы видели в фрагменте кода, который вы цитировали, либо вы назначаете выделенный объект временной переменной, сохраняете временную переменную для свойства locationManager, а затем явно освобождаете временную переменную:

CLLocationManager *_temporaryReference = [[CLLocationManager alloc] init];
self.locationManager = _temporaryReference; // this is retained
[_temporaryReference release];

Оба подхода эквивалентны с точки зрения управления памятью. Некоторые предпочитают этот второй подход, потому что им не нравится ждать, пока пул автоматического выпуска будет «очищен», особенно на устройстве с малым объемом памяти, таком как iPhone, и это обеспечивает более жесткий контроль над продолжительностью жизни объекта.

Apple Язык программирования Objective-C Документация объясняет этот атрибут более подробно.

1 голос
/ 06 мая 2010

Существует альтернатива без временной переменной или автоматического выпуска:

locationManager = [[CLLocationManager alloc] init];

Без использования self.locationManager вы не вызываете метод установки класса для этой переменной и, как следствие, не увеличиваете счет сохранения до 2. Компилятор изменяет эти назначения на [self setLocationManager: locationManager];. Это предполагает, что вы создали прототип переменной как retain.

Если это переменная класса (то есть), вы можете просто выполнить присваивание. Это спорно, является ли это хорошая практика кодирования, но на мой взгляд, это зависит от того, где он находится в классе инициации.

0 голосов
/ 30 апреля 2010

Если ваш self.locationManager является свойством, которое сохраняет его, то оно устанавливает сохранение. Делая alloc, вы устанавливаете счет сохранения +1, что означает, что к концу функции это +2. Когда вы говорите autorelease, это будет +1 (из-за сохраняющегося свойства). Вы также можете явно освободить его после установки его в свойстве, но то, что вы делаете, это меньше кода и его легко читать.

...