Проблема, с которой вы столкнулись в первом примере:
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, и объект не будет освобожден.
Что вы должны четко знать, так это:
alloc
установит счет сохранения в 1;
retain
свойства будут увеличивать счет хранения при назначении им;
autorelease
похоже на отложенное освобождение, так что в то же время (до того, как на самом деле завершено освобождение, а это означает, что в оставшейся части вашего метода и вызывающих программах вплоть до основного цикла) вы можете безопасно использовать объект, и после этого он будет освобожден.