实例被解除分配,而主要的价值观察者仍然注册

我有一个UITableView。

在这里,我得到了不同的细胞。 每个单元格都有一个模型。 使用KVO和NotificationCenter,单元会监听模型的更改。 当我离开ViewController时,我得到这个错误:

An instance 0x109564200 of class Model 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 0x109429cc0> ( <NSKeyValueObservance 0x109429c50: Observer: 0x10942d1c0, Key path: name, Options: <New: NO, Old: NO, Prior: NO> Context: 0x0, Property: 0x10968fa00> ) 

在单元格中,当模型属性设置/更改时,可以这样做:

 [_model addObserver:self forKeyPath:@"name" options:0 context:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modelIsInvalid:) name:@"modelIsInvalid" object:_model]; 

然后在cell的dealloc中:

 - (void)dealloc { NSLog(@"DEALLOC CELL"); [[NSNotificationCenter defaultCenter] removeObserver:self]; [_model removeObserver:self forKeyPath:@"name"]; } 

在模型中,我也检查它何时被释放:

 - (void)dealloc { NSLog(@"DEALLOC MODEL"); } 

在所有的模型之前,所有的单元都被释放,但是我仍然得到这个错误。 此外,我不知道如何设置错误中提到的断点。

它不会工作,因为细胞正在被重新使用。 所以当细胞离开屏幕时,它不会被释放,而是重新使用池。

你不应该在cell中注册通知和KVO。 您应该在表视图控制器中执行它,而当模型更改时,您应该更新模型并重新加载可见的单元格。

我find了答案。 我不能删除线程,有人已经回答:)也许这将是有用的人。

问题是,UITableView将出队以前使用的同一个单元格,对于较长的行(在滚动足够的时候变得可见)。

在二传手中我现在有:

 // Before we set new model if (_model) { [_model removeObserver:self forKeyPath:@"name"]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"modelIsInvalid" object:_model]; } _model = model; [_model addObserver:self forKeyPath:@"name" options:0 context:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(modelIsInvalid:) name:@"modelIsInvalid" object:_model]; 

基于接受的答案(这是正确的),你可以通过删除单元格的“ prepareForReuse ”方法的观察者来解决它。

该方法将被重新使用之前调用滚动等细胞,因此你不会有任何问题。

 - (void)prepareForReuse{ [_model removeObserver:self forKeyPath:@"name"]; } 

有可能你的视图控制器没有调用dealloc方法,因为它的引用可能被某人持有,而你的dealloc方法没有被调用。 您可以在您的viewDidUnload:viewWillDisappear:方法中删除观察者,或者您可以将控制器追踪到仪器中以进行任何保留

为单元格和可重用视图执行此操作的最佳位置是在willMove(toSuperiew)

override func willMove(toSuperview newSuperview: UIView?) { if newSuperview == nil { // check for nil means this will be removed from superview self.collectionView?.removeObserver(self, forKeyPath: "contentSize") } }