• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

[复制链接]
菜鸟教程小白 发表于 2022-12-13 08:23:58 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我认为这个问题很简单也很常见,但我仍然不明白为什么它不起作用。让我暴露上下文:

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

这样的文档会很多,我必须通过它的 Identifier 来搜索它们,而且我也会使用很多 NSFetchedResultsController。所以暂时的可能性就出来了。

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

- (instancetype)initWithEntityNSEntityDescription *)entity insertIntoManagedObjectContextNSManagedObjectContext *)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) observeValueForKeyPathNSString *)keyPath ofObjectid)object changeNSDictionary *)change contextvoid *)context {
    if (context == KVODocumentIdContext) {
        [self updateDocumentId];
    }
    else {
        [super observeValueForKeyPath:keyPath ofObjectbject 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 isEqualToNumber0]?@"":[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 -observeValueForKeyPathfObject: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:
...

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

提前致谢。

编辑:这是定义上下文的方式:

static void * KVODocumentIdContext = &KVODocumentIdContext;

编辑2:文档类继承自NSManagedObject



Best Answer-推荐答案


第一件事:我不会覆盖 initWithEntity:

这是苹果官方 NSManagedObject 类 API 文档的节选:

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

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

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

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

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap