ios - 如何创建用于 Core Data 的 sqlite 数据库?

标签 ios core-data sqlite

我的目标 是创建一个 sqlite 数据库并用数据(可能超过 1000 行)填充它,并使用这个数据库预加载核心数据,并填充一个 TableView 。

到目前为止,我已经有了使用核心数据和托管对象模型的 TableView 。我可以添加项目和删除项目 - 基本上我有 Master-Detail 模板,但使用我自己的模型。

问题: 如何以正确的格式创建 sqlite 数据库以用于 Core Data?

我已经使用提供的 sql 数据库和书中的教程成功地完成了这项工作。我注意到我教程中的表“逃亡”(例如)在提供的 sqlite 数据库中写为“ZFUGITIVE”。它的所有列都在前面附加了“Z”(“ZFUGITIVEID”、“ZNAME”...),并且存在未包含在托管中的三个额外列(“Z_PK”、“Z_ENT”、“Z_OPT”)对象模型 (.xcdatamodeld)。除了“Z”全大写名称和额外的列外,我还看到(在教程附带的这个 .sqlite 数据库中)还有两个额外的表“Z_PRIMARYKEY”和“Z_METADATA”。

我熟悉 sqlite 终端命令并且可以创建数据库,但它没有正确的格式、额外的行或带有元数据的额外表。作为实验,我所做的是采用上面的 Fugitive sqlite 数据库表并向其中添加另一个表。起初我称它为表“thing”,列为“thingID”和“title”。我为它创建了托管对象并将其连接到我的 TableView 。我一生都无法将数据预加载到核心数据/我的表格 View 中。我没有收到任何错误消息,它只是没有预加载数据(它确实允许我添加和删除新项目,就像 Master-Detail 模板一样)。

所以我将表“thing”重命名为“ZTHING”,其中包含列(“Z_PK”、“Z_ENT”、“Z_OPT”、“ZTHINGID”和“ZTITLE”),现在我收到以下错误消息。 我知道它告诉我我没有正确创建我的表,但是我找不到关于如何正确创建它的文档。请帮忙。

这是一个大的喇叭错误,基本上说明表 Z_METADATA(Z_UUID 列)中记录的版本号不正确:[或者我认为]

Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error 134100.)" UserInfo=0x5b489c0 {metadata=<CFBasicHash 0x5b4e960 [0x2651380]>{type = immutable dict, count = 7,
entries =>
    2 : <CFString 0x5b4ea40 [0x2651380]>{contents = "NSStoreModelVersionIdentifiers"} = <CFArray 0x5b4eb10 [0x2651380]>{type = immutable, count = 0, values = ()}
    4 : <CFString 0x5b4ea90 [0x2651380]>{contents = "NSPersistenceFrameworkVersion"} = <CFNumber 0x5b4e530 [0x2651380]>{value = +248, type = kCFNumberSInt64Type}
    6 : <CFString 0x5b4eac0 [0x2651380]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x5b4eba0 [0x2651380]>{type = immutable dict, count = 1,
entries =>
    1 : <CFString 0x5b4eb30 [0x2651380]>{contents = "Fugitive"} = <CFData 0x5b4eb50 [0x2651380]>{length = 32, capacity = 32, bytes = 0xe33370b6e7ca3101f91d25951e8bfe01 ... 9e50237bb313d390}
}

    7 : <CFString 0x1ee464 [0x2651380]>{contents = "NSStoreUUID"} = <CFString 0x5b4e850 [0x2651380]>{contents = "E711F65F-3C5A-4889-872B-6541E4B2863A"}
    8 : <CFString 0x1ee324 [0x2651380]>{contents = "NSStoreType"} = <CFString 0x1ee2e4 [0x2651380]>{contents = "SQLite"}
    9 : <CFString 0x5b4ea10 [0x2651380]>{contents = "NSStoreModelVersionHashesVersion"} = <CFNumber 0x5d0b520 [0x2651380]>{value = +3, type = kCFNumberSInt32Type}
    10 : <CFString 0x5b4eaf0 [0x2651380]>{contents = "_NSAutoVacuumLevel"} = <CFString 0x5b4ebf0 [0x2651380]>{contents = "2"}
}
, reason=The model used to open the store is incompatible with the one used to create the store}, {
    metadata =     {
        NSPersistenceFrameworkVersion = 248;
        NSStoreModelVersionHashes =         {
            Fugitive = <e33370b6 e7ca3101 f91d2595 1e8bfe01 3e7fb4de 6ef2a31d 9e50237b b313d390>;
        };
        NSStoreModelVersionHashesVersion = 3;
        NSStoreModelVersionIdentifiers =         (
        );
        NSStoreType = SQLite;
        NSStoreUUID = "E711F65F-3C5A-4889-872B-6541E4B2863A";
        "_NSAutoVacuumLevel" = 2;
    };
    reason = "The model used to open the store is incompatible with the one used to create the store";
}

非常感谢你能给我的所有帮助

最佳答案

好的,所以我同意上面的评论。使用 Core Data 构建您的 SQL 数据库。如果您直接修改数据库,那么就苹果可能对格式所做的一切而言,所有的赌注都将落空;但是,Apple 确实必须确保与 Core Data 的向后兼容性,因此他们的 API 必须向前迁移任何有效的最新格式的任何内容。

因此,要用真实信息(截至 2011 年 12 月和 iOS 4 是正确的)回答您的问题,这里有一种可行的技术:

  1. 首先让核心数据创建数据库。这是您的模板,将包含适当的元数据和属性。你不应该在这上面使用 DML(没有改变表等)。

  2. Z_ENT列是实体id,用于跟踪ZPRIMARYKEY表中对象的主键。如果您检查主键表,它会跟踪每个实体上已使用的最大 ID(用于生成 Z_ID)。它还跟踪继承,因为核心数据对具有继承关系的所有类使用单个表。例如。经理是员工的子类。将有一个表(zemployee),主键表将 Z_SUPER 设置为指向跟踪表 ID 的实际行。如果您有子类,则 Z_ENT 将指示该行的正确类型。例如。如果 ZPRIMARYKEY 中 Employee 为 1,Manager 为 2,则 ZEMPLOYEE 中将有 Z_ENT 为 1 和 2 的行。

  3. Z_OPT 列是一行被写入的次数的计数(包括插入...所以它从 1 开始)。它几乎肯定用于一致性(例如乐观事务并发处理)。无论如何,您应该在写入一行时递增它。

当然,你也应该保持主键表中的MAX字段是最新的。确保在事务中同时执行插入和 PK 表更新,以免损坏内容!

最后,当然,您一开始就不应该这样做 :)

我需要知道这一点,因为我需要一个非 OSX 同步服务器来处理核心数据生成的文件……因此我不能直接使用核心数据 API。

更新:2012 年 9 月

关于继承的快速说明。如果您在核心数据模型中具有来自子类的 FK 关系,则 Core Data 使用单表继承模型(在 Hibernate 文档中查找以更好地了解正在发生的事情)。单个表将 Z_ENT 设置为正确的类类型,外键可能需要多个列来处理类中存在的替代项。确保正确执行此操作的最佳做​​法是在 Objective-C 中使用每个类的实例生成一个小数据集,然后从命令行使用 sqlite3 转储数据。哪种数据类型使用哪些列将一目了然。

关于ios - 如何创建用于 Core Data 的 sqlite 数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8492843/

相关文章:

iphone - 奇怪的 `isKindOfClass` 行为

ios - ZBar:架构 armv7 的 undefined symbol

ios - 是否可以在没有 UITableView 的情况下从 Sqlite(和 CoreData)检索数据 - Swift 3

android - 插入或更新,并且仅当给定时间戳较新时才更新

java - 将 SQLite 日期整数转换为 Java 日期

ios - 两个对象没有相互接触,但 contactTestBetween() 返回结果

IOS 错误 : Google Maps does not load the map on iPhone

core-data - Swift 中的 NSManagedObject 子类不能使用自定义访问器?

iphone - NSNumber,使用和存储不同基元类型时要注意什么

Android:创建 ListView ,日期作为页眉,总数作为页脚