NSMutableArray arrayWithCapacity vs initWithCapacity - PullRequest
6 голосов
/ 28 июня 2010

Я новичок в iPhone / Objective-C с обширным опытом работы с Java.

Я узнаю больше об управлении памятью в target-c и читаю документацию Apple по управлению памятью: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

В разделе «Политика владения объектами» говорится, что вы владеете любым объектом, который создаете с помощью метода, который начинается с alloc, new или содержит копию.Владение подразумевает, что вам нужно явно 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) я должен воздержаться от использования метода класса и освободить объект, как только я закончу с ним?

Спасибо!

Ответы [ 3 ]

9 голосов
/ 28 июня 2010

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

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

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

6 голосов
/ 28 июня 2010

arrayWithCapacity: к нему уже применено автоматическое освобождение.

initWithCapacity: явно сохраняется, и вам нужно будет освободить его самостоятельно. Так как вы обычно называете его как [[A alloc] init ...], это вызовет лампочку «Мне нужно управлять памятью для этого», другие подобные магические слова, кроме «alloc», являются «new» и «copy» как Вы читаете в руководстве по управлению памятью. Но из твоего вопроса, похоже, ты хорошо понимаешь принципы этого.

Вы правы в том, что вы должны держать свой объем памяти управляемым и низким, но это не значит, что вам всегда нужно делать явные инициализацию / выпуск. Как говорит Ник, один из вариантов использования фабричных методов автоматического выпуска - это когда вы передаете их как параметры.

Другим примером является то, что когда вы добавляете что-то в коллекцию, такую ​​как NSDictionary или NSArray, это «что-то» может быть создано с помощью метода фабрики автоматического выпуска, поскольку коллекция «перехватывает» его сохранение. (Вещи сохраняются при добавлении в коллекцию и освобождаются при удалении.)

Вы можете утверждать, что

Blah *blah = [Blah blahWithSomething];
[myMutableArray addObject:blah];

просто чище, чем

Blah *blah = [[Blah alloc] initWithSomething];
[myMutableArray addObject:blah];
[blah release];

В первом случае вам вообще не нужно беспокоиться о выпускном звонке. Недостатком является то, что когда вы делаете это много раз в одном и том же цикле выполнения, объем памяти в первом случае больше, если это объект временного / одноразового массива, который исчезает в конце цикла выполнения. Но если это небольшой объект, не выполненный в цикле и сохраненный в течение более длительного времени, как это обычно бывает, их следы остаются теми же.

0 голосов
/ 28 июня 2010

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

  • если вы передаете этот массив в качестве параметра, то вы можете без проблем использовать фабричный метод, так как принимающая функция несет ответственность за его сохранение / освобождение
  • если вы хотите продолжить работу с объектом, используйте метод инициализации и в конце освободите объект
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...