gpt4 book ai didi

ios - KVO 和 Core Data - 自观察托管对象

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:14:48 25 4
gpt4 key购买 nike

我觉得这个问题很简单也很常见,但我还是不明白为什么它不起作用。让我来揭露上下文:

假设我有一个很好的核心数据模型,其中包含一个名为 Document 的实体。此文档有类型、日期、编号和版本...例如,类型:D,日期:17-10-2015,编号:24 和版本 3。本文档使用这四个值计算标识符:D20151017-24-R03

会有很多这样的文档,我将不得不通过它的标识符来搜索它们,我也会使用很多NSFetchedResultsController。所以暂时的可能性是正确的。

这是我所做的。先注册观察四个相关属性:

- (instancetype)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context {
self = [super initWithEntity:entity insertIntoManagedObjectContext:context];

if (self) {
[self addObserver:self forKeyPath:_Property(documentTypeRaw) options:0 context:KVODocumentIdContext];
[self addObserver:self forKeyPath:_Property(date) options:0 context:KVODocumentIdContext];
[self addObserver:self forKeyPath:_Property(number) options:0 context:KVODocumentIdContext];
[self addObserver:self forKeyPath:_Property(version) options:0 context:KVODocumentIdContext];
}

return self;
}

然后,在释放时注销:

- (void)dealloc {
[self removeObserver:self forKeyPath:_Property(documentTypeRaw) context:KVODocumentIdContext];
[self removeObserver:self forKeyPath:_Property(date) context:KVODocumentIdContext];
[self removeObserver:self forKeyPath:_Property(number) context:KVODocumentIdContext];
[self removeObserver:self forKeyPath:_Property(version) context:KVODocumentIdContext];
}

最后,管理通知:

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == KVODocumentIdContext) {
[self updateDocumentId];
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}

就在这里updateDocumentId:

- (void) updateDocumentId {
NSString * prefix = [self documentTypePrefix:self.documentTypeRaw];
NSString * date = [self.date documentIdFormat];
NSString * number = [NSString stringWithFormat:@"%.2d",[self.number shortValue]];
NSString * version = [self.version isEqualToNumber:@0]?@"":[NSString stringWithFormat:@"-R%.2d",[self.version shortValue]];

self.documentId = [NSString stringWithFormat:@"%@%@-%@%@",prefix,date,number,version];
}

对我来说,这应该是完美的……但是……它没有……

我有一个很好的:

failed: caught "NSInternalInconsistencyException", "<MBSDocument: 0x7fd9dbb45f40> (entity: MBSDocument; id: 0x7fd9dbb3cd00 <x-coredata:///MBSDocument/tB55CB581-AEC0-4211-A78A-7C48377BACC2612> ; data:
...
An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
Key path: date
Observed object: <MBSDocument: 0x7fd9dbb45f40> (entity: MBSDocument; id: 0x7fd9dbb3cd00 <x-coredata:///MBSDocument/tB55CB581-AEC0-4211-A78A-7C48377BACC2612> ; data:
...

我尝试了很多东西,其中包括在 observeValueForKeyPath:ofObject:change:context: 中删除对 super 的调用,或者在 init 中注册 等。但没有任何效果。好吧,我们将不胜感激。

提前致谢。

编辑:上下文是这样定义的:

static void * KVODocumentIdContext = &KVODocumentIdContext;

编辑 2: 文档类继承自 NSManagedObject

最佳答案

首先:我不会覆盖 initWithEntity:

这是 Apple 的 NSManagedObject 类官方 API 文档的摘录:

“也不鼓励您覆盖 initWithEntity:insertIntoManagedObjectContext: 或 dealloc。更改 initWithEntity:insertIntoManagedObjectContext: 方法中的值不会被上下文注意到,如果您不小心,这些更改可能不会保存。大多数初始化定制应该在其中一种清醒的……方法中执行。”

因此,您可能应该在 awakeFromInsert: 或 awakeFromFetch: 中添加这些 KVO 观察(然后在 didTurnIntoFault 中删除这些观察者)覆盖子类的方法,也许您可​​以省去添加和删除观察者的所有开销,具体取决于什么会影响您的计算属性。

如果影响计算属性的键路径不是很多关系,那么您不妨编写您的 documentID 计算属性 getter 访问器并实现类方法 +(NSSet *)keYPathsForValiesAffectingDocumentID,它返回一个包含键路径的 NSSet 如果changed 将导致使用新值重新计算计算机属性。

关于ios - KVO 和 Core Data - 自观察托管对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30975997/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com