首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实例已被释放,而键值观察者仍在其中注册。

实例已被释放,而键值观察者仍在其中注册。
EN

Stack Overflow用户
提问于 2014-07-31 10:46:42
回答 5查看 25.2K关注 0票数 16

我有一个UITableView。

我有不同的细胞。每个细胞都有一个模型。使用KVO和NotificationCenter时,单元格会听模型中的变化。当我离开ViewController时,我会得到以下错误:

代码语言:javascript
复制
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>
)

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

代码语言:javascript
复制
[_model addObserver:self
         forKeyPath:@"name"
            options:0
            context:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(modelIsInvalid:)
                                             name:@"modelIsInvalid"
                                           object:_model];

然后在细胞的去分配中:

代码语言:javascript
复制
- (void)dealloc
{
    NSLog(@"DEALLOC CELL");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [_model removeObserver:self forKeyPath:@"name"];
}

在模型中,我还检查它何时被解除分配:

代码语言:javascript
复制
- (void)dealloc
{
    NSLog(@"DEALLOC MODEL");
}

在所有模型之前,所有单元格都被取消分配,但我仍然得到了这个错误。另外,我也不知道如何设置错误中提到的断点。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-07-31 11:08:21

它不能工作,因为细胞被重复使用。因此,当单元格离开屏幕时,它没有被释放,而是被重新使用池。

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

票数 9
EN

Stack Overflow用户

发布于 2014-07-31 11:09:35

我找到了答案。我不能删除这个帖子,有人回答说:)也许它会对某人有用。

问题是,UITableView会将先前使用的单元格排出队列,让一行持续更长的时间(当滚动到足够远时,就可以看到这一点)。

在这篇文章中,我现在有:

代码语言:javascript
复制
// 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];
票数 6
EN

Stack Overflow用户

发布于 2015-11-10 14:36:34

基于接受的答案(这是正确的),您可以通过删除单元格的"prepareForReuse“方法上的观察者来解决这个问题。

在滚动时重用单元格之前将调用该方法。这样你就不会有任何问题了。

代码语言:javascript
复制
- (void)prepareForReuse{
    [_model removeObserver:self forKeyPath:@"name"];
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25056942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档