在关键价值观察员仍然注册时,“取消分配”。转换为ARC后出错

时间:2011-10-18 18:21:51

标签: ios cocoa-touch observer-pattern dealloc automatic-ref-counting

我正在使用这个课程:

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 个答案:

答案 0 :(得分:5)

我猜想didMoveToSuperview类中的方法CheckView被多次调用,导致gestureRec实例变量被重新分配,而前一个CustomTapGestureRecognizer实例被认为是没有ARC留下的引用然后被释放(导致警告消息,有人仍在观察实例)。

尝试将NSLog(@"didMoveToSuperview: self=%@ gestureRec=%@", self, gestureRec);添加到didMoveToSuperview的开头,看看是否属于这种情况。

如果是这样,快速修复可能是这样的,但我自己没有尝试过或者对代码了解很多。

- (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];   
}