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



我面临一个奇怪的泄漏。以下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

_unsafe_selfself->_unsafe_self相同,因此

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

捕获self,导致一个保留周期,防止self被释放。

这不会导致保留循环:

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

使用属性self.unsafe_self将使这在代码中更明显,但是已经有足够多的"property vs ivar"(如:-)

最新更新