转换为ARC后,出现“在仍然注册有键值观察者的情况下被释放”的错误。

4

我正在使用这个类:

https://github.com/alexleutgoeb/ALPickerView

自从我转换到ARC后,点击pickerview几次后,我会得到以下错误:

2011-10-18 14:10:19.424 MappingApp[3398:10d03] An instance 0x73c7cd0 of class CustomTapGestureRecognizer was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info: <NSKeyValueObservationInfo 0x5d93430> (<NSKeyValueObservance 0x5d933f0: Observer: 0x5d66eb0, Key path: state, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x746b180>)

错误指向CustomTapGestureRecoginizer类和该方法的最后一行:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    // Simple hack, set recognizer state to possible as tap begins
    self.state = UIGestureRecognizerStatePossible;
}

在checkview中,我有这个方法:
- (void)didMoveToSuperview {
    gestureRec = [[CustomTapGestureRecognizer alloc] initWithTarget:nil action:nil];
    gestureRec.numberOfTapsRequired = 1;
    [gestureRec addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
    [[self superview] addGestureRecognizer:gestureRec];
}

同时,我知道removeObserver可能会导致这个问题出现在checkview的dealloc中。我应该将它移动到其他地方吗?还有其他人有什么想法会导致这个问题吗?在ARC之前从未发生过。

1个回答

5
我猜测在CheckView类中的didMoveToSuperview方法被调用了多次,导致gestureRec实例变量被重新赋值,前一个CustomTapGestureRecognizer实例被ARC认为没有引用而被释放(引起警告消息,表示仍有人在观察该实例)。
尝试在didMoveToSuperview的开头添加NSLog(@"didMoveToSuperview: self=%@ gestureRec=%@", self, gestureRec);以查看是否是这种情况。
如果是这样,快速修复可能是像下面这样的代码,但我自己没有尝试过,并且对代码了解不多。
- (void)didMoveToSuperview {
  if (gestureRec != nil) {
    [gestureRec removeObserver:self forKeyPath:@"state"];
  }
  gestureRec = [[CustomTapGestureRecognizer alloc] initWithTarget:nil action:nil];
  gestureRec.numberOfTapsRequired = 1;
  [gestureRec addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
  [[self superview] addGestureRecognizer:gestureRec];   
}

不错!这很可能为你修复了一个内存泄漏问题,双赢 :) - Mattias Wadman
1
另外,您应该fork并进行pull request以在上游版本中修复此问题,如果这是一个好的修复,可能会得到一些反馈。 - Mattias Wadman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接