NSMutableArray arrayWithCapacity по сравнению с initWithCapacity

Я - 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 должен воздержаться от использования метода класса и выпустить объект, как только я сделан с ним?

Спасибо!

6
задан Tim Reddy 28 June 2010 в 05:08
поделиться

3 ответа

Обычно выбор основывается на том, собираетесь ли вы владеть объектом дольше, чем длится жизнь текущего метода (например, присвоить его какому-нибудь статическому объекту или непосредственно ivar). В этом случае вы можете использовать метод alloc/init, поскольку вы уже знаете, что хотите владеть им. Если вы планируете использовать его только в области действия текущего метода или присваиваете его чему-то управляемому, например, свойству, то, скорее всего, вы воспользуетесь методом convenience.

Когда вы знаете, что собираетесь владеть создаваемым объектом, вызов alloc/init всегда более эффективен, чем метод convenience/retain, поскольку в последнем случае требуется в основном выделить/запустить/автоосвободить объект, а затем сохранить его при возврате.

Вы также можете использовать прямые методы alloc/init, когда вы выделяете объект в цикле и не нуждаетесь/не хотите иметь дело с пулом автоматического освобождения.

9
ответ дан 8 December 2019 в 15:58
поделиться

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. Недостатком является то, что когда вы делаете это много раз в одном цикле выполнения, объем памяти в первом случае будет больше, если это временный/выбрасываемый объект массива, который исчезает в конце цикла. Но если это небольшой объект, не выполняемый в цикле и сохраняемый в течение более длительного времени, что является обычным случаем, их следы одинаковы.

6
ответ дан 8 December 2019 в 15:58
поделиться

В этом случае я стараюсь придерживаться следующих правил, чтобы избежать ошибок, связанных с памятью (== "очень неприятные"):

  • если вы передаете этот массив в качестве параметра, вы можете без проблем использовать фабричный метод , поскольку принимающая функция несет ответственность за сохранение / освобождение объекта
  • , если вы хотите продолжить работу с объектом, используйте метод инициализации и освободите объект в конце
0
ответ дан 8 December 2019 в 15:58
поделиться