Cocoa 通过非核心数据对象的绑定访问核心数据对象的属性

Cocoa 通过非核心数据对象的绑定访问核心数据对象的属性,cocoa,core-data,cocoa-bindings,Cocoa,Core Data,Cocoa Bindings,我有一组由另一个应用程序创建并以XML格式存储在磁盘上的数据。由于此数据由另一个应用程序管理,我不想麻烦将此数据加载到核心数据存储中,原因有两个:1)这将是相同数据的冗余存储,2)我必须不断更新自己的核心数据存储,以匹配另一个应用程序生成的XML文件中的更新 但是,我有在我自己的应用程序中创建的数据,这些数据需要与来自其他应用程序的XML的数据相关联,我希望将在我自己的应用程序中创建的数据保存到磁盘 为了实现这一点,来自另一个应用程序的XML数据具有与存储在XML文件中的每个对象相关联的持久、唯

我有一组由另一个应用程序创建并以XML格式存储在磁盘上的数据。由于此数据由另一个应用程序管理,我不想麻烦将此数据加载到核心数据存储中,原因有两个:1)这将是相同数据的冗余存储,2)我必须不断更新自己的核心数据存储,以匹配另一个应用程序生成的XML文件中的更新

但是,我有在我自己的应用程序中创建的数据,这些数据需要与来自其他应用程序的XML的数据相关联,我希望将在我自己的应用程序中创建的数据保存到磁盘

为了实现这一点,来自另一个应用程序的XML数据具有与存储在XML文件中的每个对象相关联的持久、唯一的ID。我将这些唯一ID存储在自己的核心数据存储中。每次启动我的应用程序时,我都会加载由另一个应用程序创建的XML数据,然后我可以通过核心数据访问我自己应用程序中的相应数据,方法是对匹配唯一ID的托管对象发出获取请求

OtherAppObject表示从XML数据加载的项。除了唯一性之外,它们还有自己独特的属性。这些其他对象由NSArrayController控制。然后是从核心数据存储中加载的MyManagedObjects,除了唯一的ID之外,还具有独特的属性

我有一个表视图,它需要显示来自OtherAppObject和MyManagedObjects的属性,因此我希望能够通过来自OtherAppObject的绑定访问和设置MyManagedObjects的属性。因此,我认为我可以为其他AppObject创建相应的MyManagedObject属性,然后通过绑定访问MyManagedObject的核心数据属性

例如,如果我想在表视图中显示OtherAppObject的属性“foo”和MyManagedObject的“bar”,我可以简单地将一个表列绑定到NSArrayController,模型键路径为“foo”,将第二个表列绑定到模型键路径为“correspondingMyManagedObject.bar”

这在不处理多个线程或传递单个托管对象上下文时有效。但由于这是“强烈反对的”,我想通过传递一个持久存储协调器,但创建单独的托管对象上下文来尝试以正确的方式实现这一点

然而,这种情况发生了变化。问题在于,当表视图尝试访问bar属性时,它需要首先访问相应的MyManagedObject属性。因此,OtherAppObject会尽职尽责地创建一个新的托管对象上下文和一个具有相应uniqueID的相应获取请求,并返回托管对象。但是这样做,它会释放托管对象上下文,现在托管对象不再有效,因此表视图无法访问bar属性

我只看到了两种方法,我想验证没有其他更简单的方法可以做到这一点:

  • 将XML数据中的对象加载到我自己的核心数据存储中。本质上,从OtherAppObject创建ManagedTotherAppObject,并与MyManagedObject建立关系,然后通过绑定进行访问将是非常好的。但是,这意味着磁盘上有相同数据的冗余存储,每次启动应用程序时,我都必须重新创建ManagedotherapoObjects(因为XML文件更新相当频繁)

  • 在OtherAppObject类上创建自定义setter/getter。例如,我会在OtherAppObject中创建
    -(NSValue*)bar
    -(void)setBar:(NSValue*)newValue
    方法。然后,我不再将表视图列绑定到其他AppObject的键值路径“correspondingMyManagedObject.bar”,而是将其绑定到其他AppObject的键值路径“bar”。这些方法将能够获取相应的MyManagedObject,并在托管对象上下文中检索或设置值,然后返回正确的值

  • 第二种方法并不特别吸引人,因为我必须为MyManagedObject的每个属性(以及与MyManagedObject有关系的其他托管对象的属性)创建两个自定义方法

    我想我可以使用keyPath:(NSString*)keyPath和
    -(void)setCoreDataProperty:(NSValue*)使用keyPath:(NSString*)keyPath
    创建通用方法
    -(NSValue*)retrievecoredatapropertyyusingkeypath:(NSString*)keyPath,但我仍然必须为每个单独的属性创建shell setter/getter

    [更新:嗯,也许我可以重写
    valueForKeyPath:
    setValue:forKeyPath:
    ,然后一切都会正常工作?]

    这是正确的,还是我遗漏了什么?

    选项1中值得一试的一种变体是设置一个持久存储协调器,将对象分割到两个单独的持久存储之间。您可以将MyManagedObject(MMO)保持不变,单独存储在磁盘上,但OtherAppObject(OAO)可以由磁盘上的某个临时存储(例如~/Library/Caches或其他内容)支持,也可以仅由内存中的存储支持

    启动时,您将创建PSC并添加包含MMO的商店。然后,您将向PSC添加第二个存储(使用
    -[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:
    ),读入XML文件并创建所有OAO,并使用
    -[NSManagedObjectContext assignObject:TopPersistentStore:
    将这些对象与该存储关联

    核心数据不允许直接建模不同商店中对象之间的关系,但您仍然可以通过唯一ID进行查找,就像现在将MMO与OAO关联一样。区别在于OAO可以简单地使用自己的托管对象上下文