Присвояване на ivars с помощта на ключова дума self в init метод на обект

Четох, че е лошо да се използва self.ivar = (удобен метод) в метода 'init' на обекта, тъй като това се забърква с наследяването.

Ако обаче знаете, че няма да подкласифицирате обекта си, добре ли е да използвате присвояването на ключова дума self?

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

Причината да питам е следната. Създавам нов обект със собствен метод init и в този метод изпълнявам различни първоначални присвоявания. Тъй като не използвам ключовата дума self, аз ги присвоявам директно на iVars и следователно използвам методите alloc вместо методите за удобство. т.е.

iVar = [[Object alloc] init];

Или ако използвам удобен метод, го запазвам. т.е.

iVar = [[Object convenienceMethod]retain]

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

Ако мога да използвам ключовата дума self плюс удобен метод вместо alloc-init, тогава това ще избегне проблема.

Ако все пак избера да използвам подхода alloc-init, къде трябва да освободя iVars?? Само в dealloc?

Благодаря за вашата помощ :)

Майкъл


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


Отговори (3)


Мисля, че вашият "обграждащ" клас не се освобождава и следователно неговият метод dealloc не се извиква, което води до това, че вашите iVars не се освобождават.

person Jay Haase    schedule 23.11.2010
comment
Почти съм сигурен, че се пуска, тъй като поставих NSLog изрази и в двата deallocs и те се отпечатват правилно. Това, което си мисля, може да е така, е как първоначално създавам обекта. Инициализирам го, като му предавам екземпляр на собствения си родител, за да задам първоначалните стойности. В неговия init метод той се записва във файл, така че освобождавам новоинициирания обект веднага щом го разпределя. Това не работи много добре и се срива, така че не го разпределям. Но не знам какво друго да направя... Опитах да го пусна автоматично, но и това се срива. - 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... Може ли да е нещо общо с факта, че класът е подклас и родителският клас не декларира, че е собствен init метод, тъй като не е необходимо да инициализира каквито и да било променливи на екземпляр...? - person Smikey; 23.11.2010
comment
Ако изтичате памет, вие не прекалявате с освобождаването, вие прекомерно запазвате. Не мисля, че родителският клас има нещо общо с това (стига да не изпуска собствените си променливи на екземпляр). - person paulbailey; 23.11.2010
comment
Освен това класът отговаря на NSCoding. Методите initWithCoder и encodeWithCoder използват инструментите за достъп, за да запазят и заредят iVars... това може би ще обърка ли броя на запазването? Уверих се, че всеки път, когато препращах към ivars извън метода init, използвах методите за достъп. - person Smikey; 23.11.2010
comment
Докато използвате аксесоарите, трябва да сте добре. - person paulbailey; 23.11.2010
comment
Може ли да прекалявам с запазването, като използвам методите за достъп извън класа? Прегледах кода си и наистина не виждам как бих могъл да прекаля със запазването на ivars в класа. - person Smikey; 23.11.2010
comment
Добре, мисля, че може да съм го намерил. Когато инициализирам екземпляр на класа, който изтича от друг клас, имам забавен проблем. Ако го инициализирам с помощта на метода init, който съм написал (който използва друг обект за определяне на първоначалните стойности, след което се записва в паметта) и след това незабавно го освободя (тъй като се записва в паметта, когато се инициализира), той се срива. Така че трябва да му изпратя брой на задържане, което означава, че е над задържан. Въпреки това не мога да го пусна без да се срине. Някакви идеи какво правя грешно тук? Не трябва ли да запазвам обекта в собствения му init?? - person Smikey; 23.11.2010