Как мне управлять памятью объектов, возвращаемых методами экземпляра? - PullRequest
4 голосов
/ 02 апреля 2009

Множество классов Objective C возвращают объекты. Например, такие утверждения, как [[instanceOfNSWhatever objectForKey:aKey] stringValue], появляются повсюду в моем (и, надеюсь, коде всех остальных).

Как мне в памяти управлять этими "промежуточными" объектами?

  • Они были только что созданы или они всегда существовали?
  • Могу ли я сохранить их, и если я выпущу объект, который их создал, они тоже будут освобождены?
  • Они автоматически выпущены?
  • Что если я запусту [instanceOfNSWhatever stringValue] миллион раз в цикле? Могу ли я распоряжаться всеми этими NSString по мере необходимости?

Я все еще изучаю ObjC, и хотя я хорошо уравновешивал свои показатели удержания в целом, мне определенно не хватает понимания того, как работают эти методы. Кто-нибудь может заполнить меня?

Ответы [ 4 ]

7 голосов
/ 02 апреля 2009

Вы, вероятно, уже читали этот раздел документации Apple по управлению памятью, но я укажу на раздел о Политике владения объектами на всякий случай. Вы несете ответственность только за управление памятью объектов, которыми вы «владеете». Цитировать документы:

  • Вам принадлежит любой созданный вами объект.
  • Вы «создаете» объект, используя метод, имя которого начинается с «alloc» или «new» или содержит «copy» (например, alloc, newObject или mutableCopy).
  • Если вы владеете объектом, вы несете ответственность за отказ от владения, когда закончите с ним. [то есть: выпуск]
  • Если вы не являетесь владельцем объекта, вы не должны освобождать его.

Раздел «Простые примеры» в этих документах дает хорошую проработку, но для того, чтобы изложить вышеприведенные вопросы в контексте ваших конкретных вопросов:

Как мне в памяти управлять этими "промежуточными" объектами?

Хорошая новость: вы этого не делаете. Игнорируйте аспект управления памятью «промежуточных» объектов в вашем примере.

  • Они были только что созданы или они всегда существовали?

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

  • Могу ли я сохранить их, и если я выпущу объект, который их создал, они тоже будут освобождены?

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

Если вы действительно сохраните его, тогда да, вы несете ответственность за выдачу соответствующего сообщения о выпуске в качестве некоторого пункта. Например, вы можете сохранить stringValue из вашего примера, если хотите сохранить это значение как свойство в своем собственном экземпляре. Objective-C использует подсчет ссылок. Если вам нужно, чтобы этот объект оставался в течение долгого времени, вы должны сохранить его, чтобы чужое сообщение об освобождении не приводило к его исчезновению, если счет сохранения упал до 0.

Они автоматически выпущены?

Зависит. Допустим, вы просите строку из instanceOfNSWhatever. Если instanceOfNSWhatever должен создать эту строку просто специально для вас (для обслуживания вашего запроса), но не заботится об этой строке, то да ... instanceOfNSWhatever, вероятно, поместит эту строку в пул автоматического выпуска. Если строка уже была свойством instanceOfNSWhatever и просто отправляла ее вам в ответ на ваш запрос, то нет, вероятно, она не была автоматически выпущена.

Опять же, красота в том, что вы не знаете и не должны заботиться. Поскольку instanceOfNSWhatever создал строку, он отвечает за ее управление. Вы можете игнорировать управление памятью, если не добавите в строку, отправив ей сообщение сохранения.

Что делать, если я запускаю [instanceOfNSWh what stringValue] миллион раз в цикле? Могу ли я утилизировать все эти строки NSS при необходимости?

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

5 голосов
/ 02 апреля 2009

Вы в основном управляете всей своей памятью в соответствии с Руководством по программированию управления памятью для какао . Короче говоря, вам нужно беспокоиться только об объектах, которые вам «принадлежат». Вы владеете объектом, если создаете его (в Какао вы создаете объект, специально выделяя его с помощью alloc или копируя его с помощью copy или одного из их производных). Если вы владеете объектом, вы обязаны освободить его, когда закончите с ним.

Следовательно, любой другой объект не принадлежит вам. Если вам необходимо использовать такой объект в течение какого-либо длительного периода (например, за пределами области, в которой вы его получили), вам необходимо специально взять на себя ответственность за объект, отправив ему сообщение retain или скопировав его.

Чтобы ответить на ваш последний вопрос, если вы создаете много временных объектов в цикле или каким-либо другим способом, вы можете создать свои собственные пулы автоматического выпуска. См. документацию для NSAutoreleasePool для получения дополнительной информации об их использовании. Однако учтите, что вам следует делать это только после того, как вы профилировали свое приложение и обнаружили, что оно использует слишком много памяти и выиграет от такого рода оптимизации.

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

2 голосов
/ 07 апреля 2009

При работе на iPhone / iPod Touch объекты автоматического освобождения освобождаются при выходе из приложения. Это может быть то, что вы не хотите. Особенно при работе с изображениями или большими кусками данных. Чтобы обеспечить быстрое освобождение больших пулов памяти, помеченных как авто-релиз, создайте локальные авто-релизы Как это:

NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];

-- do something that creates large autorelease memory blocks --

[localPool drain];

Если вы этого не сделаете, приложение неожиданно завершит работу.

1 голос
/ 02 апреля 2009

Я расскажу вам простые правила, которые я хотел бы знать, когда я впервые запустил Objective-C:)

  • Если метод содержит слова «alloc» или «copy», вы должны [отпустить] объект, когда закончите.
  • Если метод не содержит этих слов, вы должны [сохранить] его, чтобы он оставался действительным вне вашей функции.
  • Если вы звоните [сохранить], вы должны позже позвонить [освободить], когда закончите.

Это охватывает практически все, что вам нужно знать об основах управления памятью.

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

Вот почему вам не нужно публиковать результаты чего-то вроде [obj stringValue].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...