Назначение ivars с использованием ключевого слова self в методе инициализации объекта

Я читал, что использовать self.ivar = (удобный метод) в методе init и объектах плохо, так как это мешает наследованию.

Однако, если вы знаете, что не собираетесь создавать подклассы своего объекта, можно ли использовать присвоение ключевого слова self?

i.e. self.iVar = [Object objectConvenienceMethod];

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

iVar = [[Object alloc] init];

Или, если я использую удобный метод, я сохраняю его. Т.е.

iVar = [[Object convenienceMethod]retain]

Но ... когда я запускаю свою программу с включенным инструментом утечки памяти, все эти назначения идентифицируются как утечки памяти.

Если я могу использовать ключевое слово self плюс удобный метод вместо alloc-init, это поможет избежать проблемы.

Если я решу использовать подход alloc-init, где я должен выпустить iVars? Просто в освобождении?

Спасибо за вашу помощь :)

Майкл


person Smikey    schedule 23.11.2010    source источник


Ответы (3)


Я думаю, ваш "закрывающий" класс не выпускается, и, следовательно, его метод dealloc не вызывается, в результате чего ваши iVars не выпускаются.

person Jay Haase    schedule 23.11.2010
comment
Я почти уверен, что он выпускается, поскольку я поместил операторы NSLog в оба деаллока, и они печатаются правильно. Я думаю, что дело в том, как я изначально создаю объект. Я инициализирую его, передавая ему экземпляр собственного родителя для установки начальных значений. В этом методе инициализации он сохраняется в файл, поэтому я освобождаю только что созданный объект, как только я его выделил. Это происходит не очень хорошо и происходит сбой, поэтому я не отключаю его. Но я не знаю, что еще делать ... Я пробовал автосвобождение, но это тоже вылетает. - person Smikey; 23.11.2010
comment
Возможно, вы создали круговую ссылку, используя надежные ссылки. Как вы храните ссылку на родителя? Вы сохраняете ссылку на родителя? Обычно, когда дети связываются с родителями, это должно происходить через слабое звено (не сохраняется). - person Jay Haase; 23.11.2010
comment
Вы можете проверить раздел Слабые ссылки на объекты в документе: Руководство по программированию управления памятью - person Jay Haase; 23.11.2010

Нет, потому что вам нужно учитывать не только поведение подкласса - реализации суперкласса и даже поведение кода, сгенерированного фреймворком (например, синтезированные аксессоры и черная магия, используемая для реализации KVO), также могут вызывать проблемы. Это будет вероятно, но это все еще значительный шанс того, что это не так. В общем, лучше всего просто следовать рекомендациям Apple и напрямую назначать их.

Назначение ivars в init не следует сообщать как утечку в правильно работающей программе. Если вы это видите, значит, вам нужно решить еще одну проблему. Попробуйте свести проблему к минимуму, чтобы мы могли попробовать и спросить об этом - тогда мы сможем сказать, что не так.

person Chuck    schedule 23.11.2010
comment
Спасибо за ответ. Думаю, я понял, в чем заключается другая проблема - как я инициализирую новый объект ... Я написал здесь новый вопрос по этому поводу: stackoverflow.com/users/334296/smikey, если у вас есть время посмотреть :) - person Smikey; 23.11.2010

Если вы alloc или retain их в init методе вашего класса, вы должны освободить их в соответствующем dealloc методе.

person paulbailey    schedule 23.11.2010
comment
Строго говоря, вам нужно сбалансировать alloc, а не init, но обычно они идут рука об руку. - person walkytalky; 23.11.2010
comment
Но я освобождаю их с помощью метода dealloc - однако детектор утечек по-прежнему определяет их как протекающие всякий раз, когда я создаю новый экземпляр объекта ?? :( - person Smikey; 23.11.2010
comment
Если ваши удержания / выделения и выпуски сбалансированы, то утечки памяти не будет. Вы уверены, что их больше нигде не удерживают? - person paulbailey; 23.11.2010
comment
Да, я уверен. Я искал все экземпляры рассматриваемых iVars в классе, и они выпущены только в dealloc ... Может ли это быть как-то связано с тем фактом, что класс является подклассом, а родительский класс не объявляет его собственный метод инициализации, поскольку ему не нужно инициализировать какие-либо переменные экземпляра ...? - person Smikey; 23.11.2010
comment
Если вы теряете память, вы не чрезмерно ее высвобождаете, вы чрезмерно сохраняете. Я не думаю, что родительский класс имеет к этому какое-либо отношение (пока он не пропускает собственные переменные экземпляра). - person paulbailey; 23.11.2010
comment
Также класс соответствует NSCoding. Методы initWithCoder и encodeWithCoder используют аксессоры для сохранения и загрузки iVars ... возможно, это испортит счетчик сохранения? Я позаботился о том, чтобы каждый раз, когда я ссылался на ivars вне метода инициализации, я использовал методы доступа. - person Smikey; 23.11.2010
comment
Пока вы используете аксессуары, все будет в порядке. - person paulbailey; 23.11.2010
comment
Могу ли я переусердствовать с использованием методов доступа извне класса? Я прочесал свой код и действительно не понимаю, как я могу удерживать ivars внутри класса. - person Smikey; 23.11.2010
comment
Хорошо, думаю, я нашел это. Когда я инициализирую экземпляр класса, который просачивается из другого класса, у меня возникает забавная проблема. Если я инициализирую его с помощью написанного мной метода инициализации (который использует другой объект для определения начальных значений, а затем сохраняет себя в памяти), а затем немедленно освобожу его (поскольку он сохраняется в памяти при инициализации), он вылетает. Поэтому я должен отправить ему счетчик удержания, что означает, что он избыточен. Однако я не могу выпустить его без сбоя. Есть идеи, что я здесь делаю не так? Разве я не должен сохранять объект в его собственном init ?? - person Smikey; 23.11.2010