Я - iPhone/Objective-C новичок с обширным фоном Java.
Я узнаю больше об управлении памятью в цели-c, и я читаю документацию Apple относительно управления памятью: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
В разделе Object Ownership Policy это говорит владение любым объектом, который Вы создаете с помощью метода, который начинается с выделения, нового, или содержит копию. Владение подразумевает, что Вы должны явно release
объект, когда Вы сделаны с ним.
Таким образом, я смотрю на документацию NSMutableArray: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html
Существует два метода, которые в значительной степени делают то же самое... они оба создают массив с некоторой начальной способностью. Каждый - метод класса, и другой метод экземпляра.
+ (id)arrayWithCapacity:(NSUInteger)numItems;
- (id)initWithCapacity:(NSUInteger)numItems;
Теперь будучи ленивым Java-разработчиком я, почему я когда-либо предпочитал бы метод экземпляра методу класса, зная, что в какой-то момент вовремя я должен вымыться после меня?
Я предполагаю, что могу упускать ключевую суть здесь... это просто вопрос определения, когда объект выпущен? autorelease
в методе класса по сравнению с. release
в методе экземпляра? Я предполагаю, что на платформе с очень ограниченными ресурсами (iPhone) I должен воздержаться от использования метода класса и выпустить объект, как только я сделан с ним?
Спасибо!
Обычно выбор основывается на том, собираетесь ли вы владеть объектом дольше, чем длится жизнь текущего метода (например, присвоить его какому-нибудь статическому объекту или непосредственно ivar). В этом случае вы можете использовать метод alloc/init, поскольку вы уже знаете, что хотите владеть им. Если вы планируете использовать его только в области действия текущего метода или присваиваете его чему-то управляемому, например, свойству, то, скорее всего, вы воспользуетесь методом convenience.
Когда вы знаете, что собираетесь владеть создаваемым объектом, вызов alloc/init всегда более эффективен, чем метод convenience/retain, поскольку в последнем случае требуется в основном выделить/запустить/автоосвободить объект, а затем сохранить его при возврате.
Вы также можете использовать прямые методы alloc/init, когда вы выделяете объект в цикле и не нуждаетесь/не хотите иметь дело с пулом автоматического освобождения.
arrayWithCapacity: уже имеет примененное к нему автоосвобождение.
initWithCapacity: явно сохраняется, и вам придется освободить его самостоятельно. Поскольку вы обычно вызываете это как [[A alloc] init...], это вызовет лампочку "мне нужно управлять памятью для этого", другими подобными волшебными словами, кроме "alloc", являются "new" и "copy", как вы читали в руководстве по управлению памятью. Но, судя по вашему вопросу, похоже, что вы хорошо понимаете принципы этого.
Вы правы в том, что вам следует поддерживать управляемый и небольшой объем памяти, но это не означает, что вам нужно всегда делать явные init/release. Как говорит Ник, один из случаев использования фабричных методов с автоматическим освобождением - это когда вы передаете их в качестве параметров.
Другой пример: когда вы добавляете что-то в коллекцию типа NSDictionary или NSArray, это "что-то" может быть создано с помощью фабричного метода autorelease, поскольку коллекция "берет на себя" его сохранение. (Вещи сохраняются при добавлении в коллекцию и освобождаются при удалении)
Вы можете возразить, что
Blah *blah = [Blah blahWithSomething];
[myMutableArray addObject:blah];
это просто более чистый тип, чем
Blah *blah = [[Blah alloc] initWithSomething];
[myMutableArray addObject:blah];
[blah release];
В первом случае вам вообще не нужно беспокоиться о вызове release. Недостатком является то, что когда вы делаете это много раз в одном цикле выполнения, объем памяти в первом случае будет больше, если это временный/выбрасываемый объект массива, который исчезает в конце цикла. Но если это небольшой объект, не выполняемый в цикле и сохраняемый в течение более длительного времени, что является обычным случаем, их следы одинаковы.
В этом случае я стараюсь придерживаться следующих правил, чтобы избежать ошибок, связанных с памятью (== "очень неприятные"):