Утечка объекта с помощью «сохранить» - PullRequest
1 голос
/ 24 февраля 2011

У меня есть свойство, определенное с помощью атрибута retain, который я синтезирую:

@property (nonatomic, retain) UISwitch *mySwitch;

И внутри моего loadView я делаю это:

self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];

И, наконец, внутри моего dealloc я нахожусьделать это:

self.mySwitch = nil;

Утечка этого объекта (mySwitch), поскольку я использовал один alloc?Должен ли я автоматически выпустить его при назначении кадра?

Пожалуйста, предложите.

Ответы [ 4 ]

4 голосов
/ 24 февраля 2011

Строка:

self.mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];

На самом деле вызовы сохраняют дважды - один раз для alloc и снова в присваивании self.mySwitch (это свойство, которое вы указалидолжен retain любые значения, назначенные ему.) Мне сказали, что лучше всего исправить это добавить вызов autorelease в строке, сделав его:

self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];
2 голосов
/ 24 февраля 2011

Да, вы протекаете. Вы создаете собственный объект с помощью +alloc/-initWithFrame:, а затем присваиваете этот принадлежащий объект свойству, помеченному retain. Это создает вторую ссылку на объект. На этом этапе вы теряете исходную принадлежащую ссылку, что приводит к утечке самого объекта.

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

self.mySwitch = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)] autorelease];

На тангенциальной ноте не рекомендуется обращаться к свойствам внутри -dealloc. Для этого обычно приводятся две причины: 1) это будет передавать уведомления KVO, которые вам не нужны внутри -dealloc, и 2) если кто-либо переопределит сеттер (в этом классе или подклассе), он может не работать должным образом. Рекомендуемый подход - просто выпустить базовый ivar, чтобы вместо этого вы увидели что-то вроде следующего:

[mySwitch release];

Назначение nil для свойства совершенно безопасно (и рекомендуется) везде.

1 голос
/ 24 февраля 2011

В качестве альтернативы автоматическому выпуску, если вам нужно более плотное управление памятью, это должно работать для вас:

UISwitch *myswitch_tmp= [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 40, 20)];
self.mySwitch = myswitch_tmp;
[myswitch_tmp release];

и позже, например в dealloc

[mySwitch release];
0 голосов
/ 24 февраля 2011

Да. Вы пропускаете объект. Запомните одно простое правило:

если вы использовали +alloc, то всегда должно быть соответствующее -release.

...