Iphone - Назначение свойств и переменных экземпляра - PullRequest
0 голосов
/ 02 июня 2011

Ну, я до сих пор не понимаю, какие свойства объектива c и переменные экземпляра.Я создаю объект LocationManager в моем viewDidLoad.С одной стороны, LocationMan - это просто переменная экземпляра, с другой стороны, он объявлен как свойство.Посмотрите на примеры:

Первый пример:

Заголовок:

CLLocationManager* _locationMan;

Реализация:

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
_locationMan = theManager;
_locationMan.delegate = self;

Второй пример

Заголовок:

CLLocationManager* _locationMan;
@property (retain, nonatomic) CLLocationManager* locationMan;

Реализация:

self.locationMan = [[[CLLocationManager alloc] init] autorelease];
self.locationMan.delegate = self;

Какая разница между этими примерами, кроме того, что работает второйа первый нет?Что там происходит с управлением памятью?

Ответы [ 3 ]

3 голосов
/ 02 июня 2011

Проблема, с которой вы столкнулись в первом примере:

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];

вызвана использованием autorelease.Значение autorelease можно рассматривать как значение: в какой-то момент в ближайшем будущем release автоматически отобразит этот объект.Учитывая способ реализации autorelease с помощью пула релизов, это обычно происходит в следующий раз, когда поток управления возвращается в основной цикл, а пул релизов очищается.

Итак, в вашем первом случаевы создаете объект и храните его в своем иваре;но вскоре он будет выпущен, и, поскольку вы явно не сохранили его где-либо еще, он в конечном итоге будет освобожден.Когда вы получаете доступ к нему после этого, вы получаете ошибку.Если бы вы не использовали autorelease, все работало бы правильно:

CLLocationManager* theManager = [[CLLocationManager alloc] init]; //-- this is correct
_locationMan = theManager;  //-- because you assign directly to the ivar

Во втором примере создание точно такое же, это означает, что объект также будет помечен для автоматического выпуска.Но в этом случае вы назначаете его свойству, которое имеет модификатор retain.Это означает, что объект будет автоматически сохранен при назначении свойства.Таким образом, когда авторелиз на самом деле завершен (когда вы вернетесь к основному виду, примерно), у вашего объекта уже будет увеличен счет сохранения на 1;тогда автоматическое освобождение его не приведет к тому, что его счетчик сохранится равным 0, и объект не будет освобожден.

Что вы должны четко знать, так это:

  1. alloc установит счет сохранения в 1;

  2. retain свойства будут увеличивать счет хранения при назначении им;

  3. autorelease похоже на отложенное освобождение, так что в то же время (до того, как на самом деле завершено освобождение, а это означает, что в оставшейся части вашего метода и вызывающих программах вплоть до основного цикла) вы можете безопасно использовать объект, и после этого он будет освобожден.

1 голос
/ 02 июня 2011

Я пометил изменения остатков в вашем коде, возможно, это станет более понятным.

CLLocationManager* theManager = [[[CLLocationManager alloc] init] autorelease];
                                                     ^^^^^ + 1    ^^^^^^^^^^^ - 1 = 0
_locationMan = theManager;

когда ваши остатки упадут до 0, объект больше не существует.В следующий раз, когда вы попытаетесь получить к нему доступ, ваше приложение вылетает.Из-за авто-выпуска это произойдет после того, как ваш пул авто-выпуска будет истощен, в неизвестном месте в будущем, после того, как вы покинете текущий метод.Вы должны выпустить его позже, но вы можете получить к нему доступ без проблем.

0 голосов
/ 02 июня 2011

Во-первых, вы не проходите через синтезированный сеттер, который заботится о сохранении объекта. В этом случае, когда theManager автоматически освобожден, _locationManager ни к чему не цепляется, поэтому theManager освобождается.

Во втором случае используется синтезированный установщик (так как он вызывает его через self), поэтому он сохраняет theManager после его автоматического освобождения.

...