Освободете или задайте нула запазени членове

По-добре ли е да задам моите запазени членски променливи на нула или да ги освободя, когато почиствам? Задаването на запазена променлива на нула изглежда по-безопасен начин за освобождаване на обект, без да рискувате двойно извикване за освобождаване на него.

Актуализация: Позволете ми да поясня, че имам предвид променливи на член, които са настроени да имат свойството retain, т.е.:

@property (nonatomic, retain) SomeClass* mInstanceVar;

person Joey    schedule 18.03.2011    source източник
comment
Хей, Джоуи, ако съм отговорил на въпроса ти, не забравяй да отбележиш отговора ми като правилен! ;)   -  person Itai Ferber    schedule 19.03.2011


Отговори (2)


Най-добрата практика е първо да освободите променливите на екземпляра си и след това да ги зададете на nil във вашия -dealloc метод. Аз лично обичам да го правя така:

[myVar release], myVar = nil;

Ако зададете вашите променливи на екземпляр на nil, вие не ги освобождавате и причинявате изтичане на памет. Задаването им на nil след освобождаването обаче ще гарантира, че не причинявате течове и ако по някаква причина се опитате да получите достъп до тези променливи на екземпляр по-късно, няма да получите боклук памет.


Ако имате променлива на екземпляр, настроена като такава,

@property (retain) NSObject *myVar;

тогава не е добра идея да се извиква self.myVar = nil; по време на освобождаване. Ако имате обекти, които са се регистрирали за KVO известия във вашата променлива на потребителския модел, извикването на self.myVar = nil ще изпрати тези известия и други обекти ще бъдат уведомени, което е лошо, защото те ще очакват да сте все още във валидно състояние - вие не сте ако сте в процес на освобождаване.

Дори и да не са регистрирани за KVO известия, пак не е добра идея да го правите, защото никога не трябва да извиквате методи, които могат да разчитат на състоянието на вашия обект, когато състоянието му е несъвместимо (някои променливи може/ще да не съществуват) и вие трябва просто да се справите сами с процеса. [myVar release], myVar = nil; ще е достатъчно.

Ако искате повече информация, прочетете отговора на Дейв Делонг на това въпрос.


За инициализиране също не е добре да се извикват настройки на свойства и получаване (по почти същата причина като по-горе). При повикване -init бихте настроили гореспоменатата променлива като такава:

myVar = nil; // If you want to set it up as nil.
OR
myVar = [[NSObject alloc] init]; // Or set it up as an actual object.

Избягвайте self.myVar = nil и self.myVar = [[NSObject alloc] init в случаите, когато вашият клас е в неопределено състояние (тези извиквания обаче са добре в -viewDidLoad и -awakeFromNib, тъй като до този момент класът ви е напълно инициализиран и можете да разчитате на променливите на екземпляра да бъдат в пълно състояние).

person Itai Ferber    schedule 18.03.2011
comment
Или все още съм объркан, или може би съм формулирал въпроса неправилно. Исках да кажа дали имам зададено свойство за запазване на моята променлива на екземпляр. Ще актуализирам въпроса, за да отразя това. Ако вашият отговор тук се отнасяше за този случай, можете ли да разясните? Моето разбиране беше, че var със свойството retain ще запази обект при настройка с '=' и след това, когато го направя = nil; това ще освободи този обект. Това е случаят, за който питам тук. - person Joey; 19.03.2011
comment
Актуализирах обяснението си. Ако все още не е ясно, уведомете ме и ще го допълня. - person Itai Ferber; 19.03.2011
comment
Мисля, че разбирам твоето обяснение. След това уместно ли е, с контролерите на изгледа, да зададете изчистени променливи със свойството retain '= nil' в метода viewDidLoad, но вместо това да използвате [var release] в dealloc? (Това е, което наблюдавам в техните примери като примера ToolbarSearch.) - person Joey; 19.03.2011
comment
В метода -viewDidLoad е добре да използвате инструменти за настройка и получаване на свойства, защото вашият клас е напълно инициализиран дотогава. Въпреки това не е добра идея да го правите по време на -init повиквания по същата причина като dealloc повиквания. Актуализирах отговора си. - person Itai Ferber; 19.03.2011
comment
и ако наистина сте мързеливи, има макрос Three20 за извършване на стъпката освобождаване/нула... ако не използвате Three20, тогава просто напишете свой собствен макрос, за да го направите.#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER освобождаване]; __POINTER = нула; } - person Stew; 19.03.2011
comment
За всеки, който е гласувал против моя отговор, ще се радвам да знам защо. Ако има проблем в отговора ми, бих искал да го поправя. - person Itai Ferber; 21.01.2012

Ако осъществявате достъп до стойностите само чрез инструментите за достъп до свойства, просто задайте свойството на nil и то ще се освободи.

Уверете се, че сте задали всички свои свойства на nil и през dealloc.

person Cameron Hotchkies    schedule 18.03.2011