iOS (Swift):使用关系获取核心数据

iOS (Swift): Core data fetching with relationships

如果我有一个 Person 实体和一个 Book 实体,其中一个 Person 可以有很多 Book

final class Person: NSManagedObject {
    @NSManaged public fileprivate(set) var name: String
    @NSManaged public fileprivate(set) var books: Set<Book>
}

final class Book: NSManagedObject {

    @NSManaged public fileprivate(set) var name: String
    @NSManaged public fileprivate(set) var person: Person

    static func add(bookNamed name: String, to person: Person) {
        guard let context = person.managedObjectContext else { fatalError("Can not obtain managed object Context") }
        let book = NSEntityDescription.insertNewObject(forEntityName: "Book", into: context) as Book
        book.name = name
        book.person = person
    }

}

在一些 UIViewController 中,然后我将一些 Book 添加到 Person:

let alex = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: context) as Person
Alex.name = "Alex"
Book.add("first book", to: alex)
Book.add("second book", to: alex)
Book.add("third book", to: alex)

然后 Book 到另一个 Person

let john = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: context) as Person
john.name = "John"
Book.add("another first book", to: john)
Book.add("another second book", to: john)

然后我重新加载我的应用程序并使用获取请求获取 table 视图中的所有人(即 alexjohn)。然后我单击 alex,这会将我带到另一个视图控制器,它有一个 Person 的实例,我将其指定为 alex,以便我可以查看与该实例关联的书籍。

问题即使我有1000,Book是否都加载到内存中?或者,如果我想全部显示它们,是否需要执行另一次提取以获取属于 alexBook?我只是想弄清楚两个实体之间的关系发生了什么,因为它最近让我有点困惑。

感谢您的帮助。

CoreData 使用代理对象模型。当您执行获取请求时,它会透明地创建所有可直接访问的对象,作为代理。因为它们是代理而不是完整的对象,所以它们实际上并没有在创建时从数据库中加载,而是在需要时(当实际引用属性时)从数据库中加载它们同样,它们可以随时卸载如果它们未经修改且未使用。

在这种情况下,这意味着您的提取请求将为每个 Person 创建卸载的代理。当您在第一个 table 视图中显示人员姓名时,该人员的数据将加载(并缓存)在代理对象中。那时,该人引用的每本书的代理将创建为一个空代理对象。当您随后 select 这本书并显示该书的详细信息时,将从数据库中获取(缓存)实际的图书数据。

注意: 所有这些都非常依赖于实际使用的数据存储,并且仅适用于允许部分加载的存储,例如 sqlite。如果使用 XML 或 plist 存储整个对象图被实例化并加载没有空代理。