Разница в Objective C между self.variable и переменным присваиванием - PullRequest
2 голосов
/ 22 июня 2010

Боюсь, что я глупый.

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

Учитывая следующее в нужных местах.

NSString *blah;

@property (nonatomic, retain) NSString *blah;

@synthesize blah;

-(id)initWithBlah:(NSString*)b {

     self.blah = b;    //this leaks
     blah = b;         //this does not

}

У меня нет особого опыта работы с objectice c, я понимаю, что вне класса, если бы я вызывал object.blah = b; Я бы прозрачно вызывал функцию setter, которая сохраняла бы b. Внутри функции, которую я предполагаю, установив ее с помощью self.blah = b, я почему-то дважды сохраняю?

Может ли кто-нибудь объяснить мне, почему это так, или нет, что я могу делать неправильно?

Приветствия

Ответы [ 4 ]

2 голосов
/ 22 июня 2010

Вы ошибаетесь. Назначение blah = b; не имеет большого смысла, потому что после того, как ваш код возвращается из initWithBlah:, вы больше не можете полагаться на строку вокруг. Всякий раз, когда вы получаете к нему доступ в следующий раз, вполне вероятно, что он уже освобожден.

Назначение self.blah = b; является правильным, поскольку оно вызывает установщик, и, таким образом, вы вступаете во владение строкой. Конечно, вы также должны выпускать blah в вашем -dealloc, чтобы предотвратить утечки памяти.

2 голосов
/ 22 июня 2010
blah = b

Изменяет переменную экземпляра класса напрямую.

self.blah = b

вызовет средства доступа, если они есть, и, таким образом, сохранит, высвободив ресурсы по мере необходимости.

Вы должны добавить [blah release]; в ваш метод dealloc, чтобы освободить ресурс после освобождения вашего класса.

1 голос
/ 22 апреля 2013

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

т.е.

- (void)dealloc 

{

     self.blah = nil;

      or

    [self.blah release];

}
0 голосов
/ 22 июня 2010

Использование аксессора нормально, если он протекает, значит что-то не так.

В частности, ваш инициализатор должен вызываться правильно, то есть, следуя рекомендациям управления памятью какао, что параметры не принадлежат вызываемому неявно.

Таким образом, было бы хорошо, если бы она передавала автоматически выпущенную строку:

YourObj *obj = [[YourObj alloc] initWithBlah:[NSString stringWithString:@"blah"]];

При следующих утечках из-за передачи в оставшейся строке:

YourObj *obj = [[YourObj alloc] initWithBlah:[[NSString alloc] initWithString:@"blah"]];

Еще одна вещь, о которой вы должны знать, это то, что объявленные свойства не выполняют автоматическую очистку, поэтому обязательно обращайтесь с этим в -dealloc:

- (void)dealloc {
    self.blah = nil;
    // ...
}
...