2010-08-27 98 views
0

我有一组数据由另一个应用程序创建并以XML格式存储在磁盘上。由于这个数据是由这个其他应用程序管理的,我不想费心将这些数据加载到Core Data存储中,原因有两个:1)它会冗余存储相同的数据,2)我必须不断地更新我自己的Core Data存储以匹配其他应用程序生成的XML文件中的更新。通过来自非核心数据对象的绑定访问核心数据对象的属性

但是,我在自己的应用程序中创建的数据需要与来自其他应用程序的XML数据相关联,并且我想将自己的应用程序中创建的数据保存到磁盘。

要完成此操作,来自其他应用程序的XML数据具有与存储在XML文件中的每个对象关联的持久唯一ID。我将这些唯一的ID存储在我自己的Core Data存储中。在每次启动我的应用程序时,我都会加载由其他应用程序创建的XML数据,然后通过发布对与唯一ID匹配的托管对象的提取请求,可以通过Core Data在我自己的应用程序中访问相应的数据。

OtherAppObjects表示从XML数据加载的项目。除了uniqueID以外,他们还拥有自己独特的属性。这些OtherAppObjects由一个NSArrayController控制。然后我有从Core Data存储中加载的MyManagedObjects,并且除uniqueID外还具有不同的唯一属性。

我有一个表视图,需要显示来自OtherAppObjects以及MyManagedObjects的属性,所以我希望能够通过来自OtherAppObjects的绑定来访问和设置MyManagedObjects的属性。因此,我想我可以创建OtherAppObjects的相应MyManagedObject属性,然后我可以通过绑定访问MyManagedObject的Core Data属性。例如,如果我想要在表视图中显示OtherAppObjects的属性“foo”和MyManagedObjects的“bar”,我可以简单地将一个表列与NSArrayController绑定,其中模型关键字路径为“foo “,并将第二个表列绑定到”correspondingMyManagedObject.bar“的模型键路径。

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

但是,这个失败了。问题是当表视图试图访问bar属性时,它需要首先访问相应的MyManagedObject属性。因此,OtherAppObject忠实地创建一个新的托管对象上下文和一个相应的获取请求,并带有适当的uniqueID并返回托管对象。但是这样做会释放托管对象上下文,现在托管对象不再有效,因此表视图无法访问bar属性!

我只看到两个解决这个办法,我想确认没有做到这一点的另一个更简单的方法:

  1. 负载从XML数据的对象到我自己的核心数据存储。本质上,从OtherAppObjects中创建ManagedOtherAppObjects,并与MyManagedObjects建立关系,然后通过绑定进行访问将非常实用。但是,这意味着在磁盘上有相同数据的冗余存储,每次启动应用程序时(因为XML文件更新频率相当高),我将不得不重新创建ManagedOtherAppObjects。

  2. 在OtherAppObject类上创建自定义setter/getters。因此,例如,我会在OtherAppObject中创建-(NSValue *)bar-(void)setBar:(NSValue *)newValue方法。然后,我不是将表视图列绑定到OtherAppObjects的键值路径“correspondingMyManagedObject.bar”,而是将它绑定到OtherAppObjects的关键路径“bar”。这些方法将能够获取相应的MyManagedObject和检索或内管理对象范围内设置的值,然后返回正确的值。

该第二方法没有特别吸引人的,因为我不得不创建MyManagedObject的每一个属性(其他管理对象进行MyManagedObject有关系的特性)两个自定义的方法。

我想我可以创建广义方法-(NSValue *)retrieveCoreDataPropertyUsingKeyPath:(NSString *)keyPath-(void)setCoreDataProperty:(NSValue *)newValue usingKeyPath:(NSString *)keyPath,但我仍然必须为每个单独的属性创建shell setter/getters。

[更新:嗯,也许我可以只覆盖valueForKeyPath:setValue:forKeyPath:,然后就不会有什么问题OK?]

这是正确的,还是我失去了一些东西?在选项#1

回答

0

一个变化,可能是值得一试。将设置的东西,让你有一个持久存储协调其将两个单独的持久性存储的对象。你可以保持MyManagedObjects(MMO)相同,单独存储在磁盘上,但是OtherAppObjects(OAO)可以通过临时存储在磁盘上(例如在〜/ Library/Caches或其他)内存存储。

一经推出,您将创建您的PSC和添加包含大型多人在线游戏商店。然后,您可以添加第二个店的PSC(使用-[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]),在XML文件中读取和创建所有OAOs,并使用-[NSManagedObjectContext assignObject:toPersistentStore:]那家商店的那些对象相关联。

核心数据不允许在不同的商店对象之间的直接建模的关系,但是就像你现在在做与OAO一款MMO关联,你可以仍然可以通过唯一的ID做查找。区别在于OAO可以简单地使用自己的托管对象上下文来获取MMO,因此您可以确信MMO至少会像OAO一样长。

然后,当您退出应用程序时,您可以删除〜/ Library/Caches中的临时存储,或者如果使用内存存储,只需让它消失到以太网中, MMO完好无损。

+0

这是一个有趣的想法。我试着实现它。它的工作原理与广告一样,有一个非常大的缺点:性能是不可接受的。 保持对不同商店中托管对象的引用的唯一方法似乎是通过提取请求。所以现在,当我想通过OAO(它们本身就是管理对象)访问MMO的属性时,我会通过OAO的“对应的MyManagedObject”属性,这只是一个获取请求。产生数以千计的这些取从表视图结果的请求在等待两分钟,应用程序启动时,当它是先前2秒 – 2010-09-01 04:14:47

+0

嗯,发生,我认为我可以通过的objectID存储对对象的引用,而不是需要一个取指令请求。 ..这个想法可能还有效。 – 2010-09-01 04:54:14

+0

如果确实使用objectID,请注意临时ID,并确保只保存永久ID。 – 2010-09-02 04:39:43