Управление памятью в iOS / ManagedObjectContext
Похоже, я не понял управления памятью в Objective C... вздох.
У меня есть следующий код (обратите внимание, что в моем случае, placemark.thoroughfare
а также placemark.subThoroughfare
оба заполнены действительными данными, таким образом оба if
условия будут TRUE
item
привязан к ManagedObjectContext
, Управляемые переменные в item
такие как place
есть сеттеры / геттеры, созданные с @dynamic
, Таким образом, декларация
@property (nonatomic, retain) NSString *place;
@dynamic place;
Позже в коде, в ReverseGeocoderDelegate, я получаю к нему доступ:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {
if (placemark.thoroughfare) {
[item.place release];
item.place = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
} else {
[item.place release];
item.place = @"Unknown Place";
}
if (placemark.thoroughfare && placemark.subThoroughfare) {
// *** problem is here ***
[item.place release];
item.place = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
Если я не отпущу item.place
в отмеченном месте в коде Instruments обнаруживает утечку памяти. Если я это сделаю, программа вылетает, как только я пытаюсь получить доступ item.place
вне оскорбительного метода.
Есть идеи?
2 ответа
Прежде всего, я бы изменил логику так:
NSString *newPlace = nil;
if (placemark.thoroughfare && placemark.subThoroughfare) {
newPlace = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
else {
if (placemark.thoroughfare) {
newPlace = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
}
else {
newPlace = @"Unknown Place";
}
}
item.place = newPlace; // Either nil of valid string can be assigned to
Использование release для простой повторной инициализации указателя многими не рекомендуется. Вам не нужно делать это, если это нужно для сохранения памяти.
Ваша предыдущая логика выпускает дважды. То, что делает релиз изначально, просто уменьшается retainCount
, Если это 0, то объект освобожден. Объект не будет освобожден до его retainCount
это 0.
Предполагая, что ваш предмет имеет свойство сохранить и с stringWithFormat:
возвращается autoreleased
строка, поэтому во 2-м выпуске вы пытались выпустить то, что должно было быть autoreleased
тем не мение.
Лучший способ очистить объект несколько раз - просто назначить nil
к этому.
Отправной точкой было бы перечитать свойства, потому что вам не нужно нигде делать "[item.place release]". Таким образом, вы можете удалить их. Динамический код, созданный средой выполнения для включения этого свойства, автоматически обрабатывает освобождение всего, что ему было ранее назначено.
Так же [NSString stringWithFormat:...
создает объект автоматического освобождения (не уверен, если вы знали, что:-), что означает, что если вы вручную управляете памятью для переменной (не для свойства), вам придется сохранить / освободить ее. Но потому что вы используете свойства, вы не делаете.
Я не могу понять, почему инструменты обнаруживают утечку памяти. Возможно, какой-то код выше связан с этим. Например, если вы пошли item.place = [NSString alloc] initWith...];
тогда я думаю, что тебе это понадобится.
Я подозреваю, что произошел сбой из-за выпусков, приводящих к тому, что счетчики сохраняются равными нулю, и запускающих ошибочные ошибки доступа.
Надеюсь, это поможет.