【发布时间】:2023-03-22 08:03:01
【问题描述】:
我在这里查看一个表格视图单元格,我找到了这段代码:
- (void)awakeFromNib {
[super awakeFromNib];
[self addObserver:self forKeyPath:@"model.isDownloading" options:NSKeyValueObservingOptionNew context:NULL];
[self addObserver:self forKeyPath:@"model.isCached" options:NSKeyValueObservingOptionNew context:NULL];
[self addObserver:self forKeyPath:@"model.isOutDated" options:NSKeyValueObservingOptionNew context:NULL];
[self addObserver:self forKeyPath:@"model.cacheUpdateDate" options:NSKeyValueObservingOptionNew context:NULL];
[self addObserver:self forKeyPath:@"model" options:NSKeyValueObservingOptionNew context:NULL];
}
观察者在dealloc 方法中被移除。 model 是 weak 属性,接收托管对象(核心数据)。
我收到虚假崩溃,告诉我托管对象已删除,但仍有观察者注册。
为什么会发生错误对我来说很清楚:该对象在后台某处被删除,但仍链接到 tableview 的单元格。由于单元格上的dealloc 在应用程序的生命周期中基本上不会被调用,因此观察者永远不会被真正删除。由于对核心数据对象的引用是weak,因此它将在后台静默释放 - 至少尝试这样做。这失败了,因为模型仍然被观察到。
我有一些问题:
- 如果观察到类似“model.isDownloading”的路径,那么观察者注册在
model对象中,而不是在self的setter 中,对吗? - 如果
model被重新分配(self.model = newThing要求,removeObserver在分配model之前调用model,并且观察者需要在newThing上注册,objC 是否足够聪明以处理观察者的变化之后)。 - 由于崩溃发生在托管对象的dealloc上,我认为一个简单的解决方案是,使
model强而不是weak,当然要确保它正确设置为nilprepareForReuse:。这是否有我没有意识到的副作用?
错误信息是:
class xxx was deallocated while key value observers were still registered with it
【问题讨论】:
-
我认为 tableview 正在重用单元格,也许尝试删除 uitableviewcell 的 prepareForReuse 方法上的观察者
-
这不是重点。我知道细胞被重复使用了。当单元被重用时,模型被设置。看起来 KVO 正确地管理了这个变化。然而,对象消失在背景中,而细胞没有意识到。这就是为什么我认为我需要使用
strong属性而不是弱属性来保留引用。
标签: ios objective-c uitableview key-value-observing