/ / Por que esse código vaza no ARC? (Uma __variável de instância fraca) - objetivo-c, cacau

Por que esse código vaza no ARC? (Uma variável de instância __weak) - objective-c, cacau

Estou enfrentando um vazamento estranho. Objetos do seguinte Car classe nunca é desalocada.

No entanto, se eu me livrar da variável de instância _unsafe_self e, em vez disso, declare (e atribua como antes) a variável dentro do init método, o vazamento vai embora.

O que poderia estar causando isso? eu pensei __weak sempre foi fraco, seja uma variável de instância ou não.

@interface Car : NSObject
@end

@implementation Car {
id _obs;
__weak Car *_unsafe_self;
}

- (id)init {
if (!(self = [super init]))
return nil;

_unsafe_self = self;

_obs = [[NSNotificationCenter defaultCenter]
addObserverForName:NSWindowDidMoveNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
NSLog(@"hello %@", _unsafe_self);
}];

return self;
}

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:_obs];
}
@end

Respostas:

9 para resposta № 1

_unsafe_self é o mesmo que self->_unsafe_self, portanto, o bloco em

_obs = [[NSNotificationCenter defaultCenter]
addObserverForName:NSWindowDidMoveNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
NSLog(@"hello %@", _unsafe_self);
}];

captura self, causando um ciclo de retenção que impede self de ser desalocado.

Isso não causa um ciclo de retenção:

__weak Car *weakSelf = self;
_obs = [[NSNotificationCenter defaultCenter]
addObserverForName:NSWindowDidMoveNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
NSLog(@"hello %@", weakSelf);
}];

Usando uma propriedade self.unsafe_self tornaria isso mais óbvio no código, mas já existem perguntas e respostas mais do que suficientes sobre "propriedade vs ivar" :-)