使用 CoreData,如果我有一个 @dynamic 属性,我可以像 @synthesized 一样覆盖它的 getter 吗? (惰性实例化)

Posted

技术标签:

【中文标题】使用 CoreData,如果我有一个 @dynamic 属性,我可以像 @synthesized 一样覆盖它的 getter 吗? (惰性实例化)【英文标题】:With CoreData, if I have an @dynamic property, can I override its getter just like it was @synthesized? (Lazy Instantiation) 【发布时间】:2013-04-06 17:08:10 【问题描述】:

我使用 CoreData 创建了一个实体,然后将其子类化到它自己的文件中,其中包含 @propertys,然后在 .m 文件中包含 @dynamic 部分。

当我希望某个从未设置过的东西具有一定的价值时,我总是使用惰性实例化,如下所示:

- (NSString *)preview 
    if ([self.body length] < 200) 
        _preview = self.body;
    
    else 
        _preview = [self.body substringWithRange:NSMakeRange(0, 200)];
    

    return _preview;

但是我如何使用@dynamic 属性来做到这一点?如果我做同样的事情,它会说 _preview 是一个未声明的属性,但它在 .h 文件中。我对惰性实例化有什么不同?

【问题讨论】:

它说_preview 是一个未声明的标识符,因为您没有具有该名称的变量。 @synthesize 创建变量; @dynamic 没有。 【参考方案1】:

一种标准方法是在Core Data 模型中将preview 定义为transient 属性(这样该值实际上并不存储在数据库中),并实现自定义getter 方法。在您的情况下,它看起来像:

- (NSString *)preview

    [self willAccessValueForKey:@"preview"];
    NSString *preview = [self primitiveValueForKey:@"preview"];
    [self didAccessValueForKey:@"preview"];
    if (preview == nil) 
        if ([self.body length] < 200) 
            preview = self.body;
         else 
            preview = [self.body substringWithRange:NSMakeRange(0, 200)];
        
        [self setPrimitiveValue:preview forKey:@"preview"];
    
    return preview;

(您可以为@dynamic 属性提供自定义的getter、setter 方法。但是,Core Data 属性不只是由实例变量支持。这就是你不能的原因 访问_preview。)

如果您需要在body 属性发生变化时重新计算preview,那么您 还必须为body 实现一个自定义设置方法,将preview 设置回nil

有关更多信息,请阅读“核心数据编程指南”中的Non-Standard Persistent Attributes。

更新: Core Data Programming Guide 的当前版本 不再包含该章节。您可以找到存档版本 来自Way Back Machine。当然,这必须与 一粒盐,因为它不是官方文档的一部分 没有了。

【讨论】:

@satheeshwaran:谢谢。 只需要使用那个方法吗?或者我必须在 CoreData 文件中做些什么? @user212541:应该就是这样。您只需在 Core Data 模型编辑器中将预览属性标记为瞬态。 它究竟是如何复制数据的? @SAHM:是的,不幸的是,Apple 删除了 Core Data Programming Guide 的几个章节以及最近的更新(您可能想向 Apple 提交错误报告!)。我在我的答案中添加了一个存档版本的链接。【参考方案2】:

See documentation 使用 primitiveValueForKey:

基本上:

@dynamic name;

- (NSString *)name

    [self willAccessValueForKey:@"name"];
    NSString *myName = [self primitiveName];
    [self didAccessValueForKey:@"name"];
    return myName;


- (void)setName:(NSString *)newName

    [self willChangeValueForKey:@"name"];
    [self setPrimitiveName:newName];
    [self didChangeValueForKey:@"name"];

【讨论】:

以上是关于使用 CoreData,如果我有一个 @dynamic 属性,我可以像 @synthesized 一样覆盖它的 getter 吗? (惰性实例化)的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法为 Core Data 原始访问器自动生成 @property 和 @dynamic 标签?

OCMock:存根 @dynamic 属性

CoreData NSManagedObject 已损坏

Coredata关系实体创建

在 CoreData 中迁移实体父级

如果没有数据,带有 @FetchRequest (SwiftUI) 和 NSPredicate 的 CoreData 会崩溃