如何在 Core Data 模型中动态创建新实体(表)?

Posted

技术标签:

【中文标题】如何在 Core Data 模型中动态创建新实体(表)?【英文标题】:How to dyanmic create a new entity (table) via CoreData model? 【发布时间】:2011-03-17 16:08:04 【问题描述】:

我想在 SQLite 中创建一个新的实体(表)。我的代码如下:

+(BOOL)CreateDataSet:(NSManagedObjectModel *) model  
    attributes:(NSDictionary*)attributes 
    entityName:(NSString*) entityName 
 
    NSEntityDescription *entityDef = [[NSEntityDescription alloc] init];

    [entityDef setName:entityName];
    [entityDef setManagedObjectClassName:entityName];
    [model setEntities:[NSArray arrayWithObject:entityDef]];
    NSArray *properties =   [CoreDataHelper CreateAttributes:attributes];
    [entityDef setProperties:properties];

    [entityDef release];

    return TRUE;

但它会引发错误:

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序, 原因:“无法修改不可变模型。” *** 第一次抛出调用堆栈: ( 0 核心基础 0x01c5abe9 __exceptionPreprocess + 185 1 libobjc.A.dylib 0x01daf5c2 objc_exception_throw + 47 2核心数据0x0152634a-[NSManagedObjectModel(_NSInternalMethods)_throwIfNotEditable]+106 3 核心数据 0x01526904 -[NSManagedObjectModel setEntities:] + 36 ……

这似乎表明模型是只读的。

【问题讨论】:

警告:Core Data 不是 SQL。实体不是表格。对象不是行。列不是属性。 Core Data 是一个对象图管理系统,它可能会也可能不会持久化对象图,并且可能会或可能不会在幕后使用 SQL 来做到这一点。试图用 SQL 术语来思考 Core Data 会导致您完全误解 Core Data 并导致很多痛苦和浪费时间。 【参考方案1】:

From the documentation:(重点是我的)

托管对象模型是可编辑的 直到它们被对象图使用 管理器(托管对象上下文或 持久存储协调器)。这 允许您创建或修改它们 动态的。但是,一旦模型 使用中,不得更改。 这是在运行时强制执行的——当 对象管理器首先获取数据 使用模型,整个模型 变得不可编辑。任何试图 改变一个模型或它的任何一个 该点之后的子对象会导致 要抛出的异常。 如果您需要 修改正在使用的模型,创建 副本,修改副本,,然后 丢弃旧物 型号。

【讨论】:

但是怎么做呢?我尝试新建模型并使用 NSPersistentStoreCoordinator 方法 'addPersistentStoreWithType:configuration:URL:options:error' 将模型保存为新的 sqlite 文件,但失败......【参考方案2】:

我引用了 Apple 的文档,它非常准确地描述了它:

实体描述是可编辑的,直到 它们被对象图使用 经理。这允许您创建或 动态修改它们。然而,有一次 使用了描述(当 托管对象模型 属于与一个相关联 持久存储协调器),它必须 不能(确实不能)改变。这 在运行时强制执行:任何尝试 改变一个模型或它的任何一个 模型后的子对象 与持久存储相关联 协调器导致异常 抛出。如果您需要修改模型 正在使用中,创建副本,修改 副本,然后丢弃对象 使用旧模型。

【讨论】:

我们如何用新创建的模型替换旧模型?【参考方案3】:

来自NSManagedObjectModel 的文档:

以编程方式编辑模型

托管对象模型是可编辑的 直到它们被对象图使用 管理器(托管对象上下文或 持久存储协调器)。这 允许您创建或修改它们 动态的。但是,一旦模型 使用中,不得更改。 这是在运行时强制执行的——当 对象管理器首先获取数据 使用模型,整个模型 变得不可编辑。任何试图 改变一个模型或它的任何一个 该点之后的子对象会导致 要抛出的异常。如果你需要 修改正在使用的模型,创建 副本,修改副本,然后 丢弃旧物 型号。

换句话说,在设置持久存储协调器或托管对象上下文之前编辑托管对象模型。

【讨论】:

嗨,可以为此目的显示一些代码吗?非常感谢【参考方案4】:

如果你想动态创建实体请忽略CoreData,试试SQLite(请使用神奇的FMDB库),它不会让你失望的。

请注意,SQLite/FMDB 不支持 iCloud。

【讨论】:

以上是关于如何在 Core Data 模型中动态创建新实体(表)?的主要内容,如果未能解决你的问题,请参考以下文章

Core Data - 如何在不同的上下文中建立两个对象之间的关系

在 Core Data 中为实体添加属性

Core Data 自动迁移不会在我的新模型中创建新实体

在 Swift Core Data 中保存没有关系的实体

如何在 Core Data 中创建数据模型?

如何在 iOS 上的 Core Data 中设置新创建的关系?