为什么这个代码在ARC下泄漏?(一个__weak实例变量)

7co*_*ows 3 cocoa objective-c

我面临一个奇怪的泄漏.以下Car类的对象永远不会被释放.

但是,如果我摆脱了实例变量_unsafe_self,而是在方法中声明(并像之前那样分配)变量init,那么泄漏就会消失.

可能是什么导致了这个?我认为__weak总是很弱,无论它是否是实例变量.

@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
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 9

_unsafe_self是相同的self->_unsafe_self,因此在块中

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

捕获self,导致保留周期,防止self被解除分配.

这不会导致保留周期:

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

使用属性self.unsafe_self会使代码中的这一点更加明显,但已经有足够的"属性与ivar"Q&As :-)