Что увеличивает показатель удержания объекта?
Вот код, который я имею в виду.
// Person.h
@interface Person : NSObject {
NSString *firstName;
NSString *lastName;
}
@end
// Person.m
@implementation Person
- (id)init {
if (![super init]) return nil;
firstName = @"John";
lastName = @"Doe";
}
@end
// MyClass.m
@implementation MyClass
.....
- (NSArray *)getPeople {
NSMutableArray *array = [[NSMutableArray alloc] init];
int i;
for (i = 0; i < 10; i++) {
Person *p = [[Person alloc] init];
[array addObject:p];
}
return array;
}
.....
@end
Теперь, я знаю, что в этом примере кода отсутствует управление памятью. Что потребуется?
В цикле getPeople я назначаю Person (preserveCount 1), а затем добавляю его в массив. Счет сохранения теперь равен 2, правильно? Если это два, я должен быть [p release] после добавления его в массив, возвращая значение keepCount в 1?
Правильно ли я в том, что ответственность вызывающего абонента заключается в том, чтобы освободить массив, возвращаемый методом? (Что также освободит память персонажа и их переменных экземпляра, если их количество будет равно 1).
Я прочитал документ управления памятью Apple, но я думаю, что я больше всего не понимаю, это то, что увеличивает количество объектов, удерживающих счет? Я думаю, что я понимаю идею того, кто несет ответственность за освобождение. Это основное правило, согласно Apple:
Вы получаете право собственности на объект, если его создаете с помощью метода, имя которого начинается с "alloc" или "new" или содержит "copy" (например, alloc, newObject или mutableCopy), или если вы отправляете сохранить сообщение. Вы несете ответственность за отказ от владения собственными вами объектами с помощью выпуска или авторекламы. В любой другой момент, когда вы получаете объект, вы не должны его отпускать.
Предложение bobDevil "только беспокоиться о том, что количество удержаний, которое вы добавляете в элемент явно, заставило его щелкнуть по мне. После прочтения политики собственности в Apple, по сути, объект/метод, создавший новый объект, является ответственным за освобождение/его/интерес к нему. Правильно ли это?
Теперь скажем, что я метод, который получает объект, и присваивает его переменной экземпляра. Мне нужно сохранить полученный объект правильно, поскольку у меня все еще есть интерес к нему?
Если это неверно, сообщите мне.
Ответы
Ответ 1
Вы правы, что счетчик сохранения равен 2 после добавления его в массив. Однако вы должны только беспокоиться о том, что вы сохраняете счет, который вы добавляете к элементу явно.
Сохранение объекта - это контракт, в котором говорится: "Я не с тобой, не уходи". Основное эмпирическое правило (есть исключения, но они обычно документируются) заключается в том, что вы являетесь владельцем объекта при назначении объекта или создании копии. Это означает, что вам задан объект со значением удержания 1 (не автореализованным). В этих двух случаях вы должны освободить его, когда закончите. Кроме того, если вы когда-либо явно сохраняете объект, вы должны его освободить.
Итак, чтобы быть конкретным для вашего примера, когда вы создаете Личность, у вас есть на нем счет. Вы добавляете его в массив (который делает что угодно с ним, вам все равно), а затем вы закончите с Person, поэтому вы его отпустите:
Person *p = [[Person alloc] init]; //retain 1, for you
[array addObject:p]; //array deals with p however it wants
[p release]; //you're done, so release it
Кроме того, как я уже сказал выше, вы только владеете объектом во время выделения или копирования в целом, поэтому, чтобы быть совместимым с этим с другой стороны, вы должны вернуть массив autoreleased, чтобы вызывающий метод getPeople не владеют им.
return [array autorelease];
Изменить: Правильно, если вы его создадите, вы должны его освободить. Если вы вкладываете в него проценты (через сохранение), вы должны его освободить.
Ответ 2
Сохраняемые подсчеты увеличиваются, когда вы вызываете alloc специально, поэтому вам нужно будет его явно освободить.
Обычно методы factory предоставляют вам автореализованный объект (например, [NSMutableArray array]), вам нужно будет специально сохранить это, чтобы поддерживать его в течение некоторого времени.).
Что касается NSArray и NSMutableArray addObject:, кому-то придется комментировать. Я считаю, что вы относитесь к классам как к черным ящикам с точки зрения того, как они обрабатывают свое управление памятью как шаблон дизайна, поэтому вы никогда не сможете явно опубликовать что-то, что вы передали в NSArray. Когда он разрушается, он должен обрабатывать декремент самого счета.
Вы также можете получить некоторое неявное сохранение, если вы объявите свои ivars как свойства, такие как @property (сохранить) suchAndSuchIvar, и используйте @synthesize в своей реализации. Synthesize в основном создает сеттеры и геттеры для вас, и если вы вызываете (сохраняете) конкретно, сеттер собирается сохранить переданный ему объект. Это не всегда очевидно, потому что сеттеры могут быть структурированы следующим образом:
Person fart = [[Person alloc] init];
fart.firstName = @"Josh"; // this is actually a setter, not accessing the ivar
// equivalent to [fart setFirstName: @"Josh"], such that
// retainCount++
Edit:
И что касается управления памятью, как только вы добавляете объект в массив, вы закончите с ним... так:
for (i = 0; i < 10; i++) {
Person *p = [[Person alloc] init];
[array addObject:p];
[p release];
}
Джош
Ответ 3
Вы должны/не быть/беспокоиться об удержании счета. Это внутренне реализовано. Вам нужно только заботиться о том, хотите ли вы "владеть" объектом, сохранив его. В приведенном выше коде массив должен владеть объектом, а не вы (вне цикла, в котором вы даже не ссылаетесь на него, кроме массива). Поскольку у вас есть [[Person alloc] init]
, вам необходимо его освободить.
Таким образом,
Person *p = [[Person alloc] init];
[array addObject:p];
[p release];
Кроме того, вызывающий "getPeople" не должен владеть массивом. Это соглашение. Сначала вы должны авторейтировать его.
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
Вы захотите прочитать документацию Apple по управлению памятью: http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html