核心数据。使用常量文字作为属性名称的 NSPredicate 问题

Posted

技术标签:

【中文标题】核心数据。使用常量文字作为属性名称的 NSPredicate 问题【英文标题】:Core data. NSPredicate issue using constant literals as names of properties 【发布时间】:2014-05-05 13:36:25 【问题描述】:

我有 NSManagedObject 的属性。假设它是一个属性:

@property (retain, nonatomic) NSString *city;

为了从核心数据中获取数据,我总是使用NSPredicate。谓词如下所示:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"city", @"San Francisco"];

但是这里的问题是项目使用键“城市”作为未定义的键,含义就像一个常量。因此,假设我在我的应用程序中使用键“城市”1000 次,那么如果 NSManagedObject 的属性发生更改,我需要用新的键替换所有这些键,例如到城市名。在这种情况下,我需要使用谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"cityName", @"San Francisco"];

不舒服。所以现在我正在使用全局extern NSString key kCity = @"city";,但如果数据模型也发生了变化,那么就会出现问题,因为如果属性会发生变化,我只会在运行应用程序和控制台时才会崩溃:

'key path city not found in entity <NSSQLEntity...

这里有哪些解决方法?我想使用类似的东西

NSString * const kCity = myEntity.city.propertyString;

所以如果属性被更改,解析器会告诉我项目有错误,我无法运行 app.因此,在我将属性更改为常量之后,我才能运行应用程序

如何获取 NSString 中的属性名称。当然这只是建议,也许有人有其他变体。

谢谢

【问题讨论】:

【参考方案1】:

您可以使用mogenerator,它所做的一件事就是为您可以使用的属性和关系键创建struct

// .h
extern const struct MBListAttributes 
    __unsafe_unretained NSString *title;
 MBListAttributes;

// .m
const struct MBListAttributes MBListAttributes = 
    .title = @"title",
;

然后您可以使用MBListAttributes.title 来获取正确的密钥。

【讨论】:

对于 mogenerator 的这个和其他一些(可能鲜为人知的)功能,请参阅What features does mogenerator provide?。 我该如何使用它。有人可以分享安装指南的链接吗?我有主要的想法,但是 repo 中没有关于如何开始使用它的步骤。也许我错过了什么。另外我正在使用 MagicalRecord,如果 mogenerator 因为 fetch 或其他原因,它会影响某些部分吗?【参考方案2】:

当我想要一个键的名称时,我使用this 基于宏的解决方案来避免字符串文字。

它允许您以这种方式编写键名:

[NSPredicate predicateWithFormat:@"%K = %@", Key(YourManagedObjectSubclass, propertyName), @"aValue"];

编译器将检查 YourManagedObjectSubclass 是否具有给定名称的属性。

当然,请记住,如果您在数据模型中更改属性名称,您仍然需要在 NSManagedObject 子类中进行更改。

【讨论】:

以上是关于核心数据。使用常量文字作为属性名称的 NSPredicate 问题的主要内容,如果未能解决你的问题,请参考以下文章

从核心数据读取时获取属性名称和值

你可以在javascript中使用模板文字创建对象属性名称吗?

java中的常量和属性

获取常量文件中具有属性名称的会话属性

为啥新的 Visual Studio 将字符串文字作为指向常量的指针?

带有核心数据对象的 NSPredicate