如何持久化存储NSManagedObjectID?

4
为了避免成为XY问题,这里提供一些背景信息:
我的应用程序允许用户创建和保存许多设置,有点像Xcode的字体和颜色选择器。

enter image description here

这是因为用户可以设置很多东西。只需点击已保存的设置,而不是再次设置所有这些内容,会更容易一些。
我使用Core Data存储用户保存的设置。用户创建的每个设置都是一个NSManagedObject子类的实例。现在,我需要持久地存储所选的设置,以便当应用程序重新打开时,用户将选择与之前相同的设置。
我的第一个想法是将NSManagedObject子类实例存储在NSUserDefaults中。但根据文档,除非将其转换为NSData,否则无法存储它:
默认对象必须是属性列表,即NSData、NSString、NSNumber、NSDate、NSArray或NSDictionary的实例(或对于集合,这些实例的组合)。
然后我尝试存储NSManagedObject子类实例的objectID。我看到有一个URIRepresentation()方法返回一个NSURL。所以我认为这会起作用:
NSData(contentsOfURL: selectedOption!.objectID.URIRepresentation())

但是初始化程序以某种方式失败了。

现在我意识到这是一个愚蠢的想法,因为即使我可以将其转换为NSData,我也无法将NSData转换回NSManagedObjectID

根据这个问题,OP似乎能够存储对象ID:

我将所选主题的对象ID存储在NSUserDefaults中,以便当应用程序重新启动时,所选的主题仍然存在。

我该怎么做?


1
你可以将URIRepresentation的字符串值简单地存储在NSUserDefaults中。稍后,您可以加载该字符串,然后使用managedObjectIDForURIRepresentation获取NSObjectId,然后使用objectWithID获取NSManagedObject。 - Paulw11
@Paulw11 那我该如何将字符串转换为相应的NSManagedObject呢? - Sweeper
1
就像我之前所说的那样,通过向 managedObjectIDForURIRrepresentation 提供 URL 并提供返回的对象 ID 到 objectWithID,您可以在托管对象上下文中操作对象。 - Paulw11
1
为什么不在数据存储中存储一个标志来指示当前选择,或者使用与当前内容相关的当前设置实体 - 您根本不需要使用对象ID... - Wain
1个回答

6

NSUserDefaults 提供了 "便利方法"。

public func setURL(url: NSURL?, forKey defaultName: String)
public func URLForKey(defaultName: String) -> NSURL?

这里提到了使用URIRepresentation()获取的类似于NSURL的对象的存储和检索。转换为和从NSData中进行,处理过程是透明的。根据文档描述:

当使用-[NSUserDefaults setURL:forKey:]存储一个NSURL时,会进行一些调整:

  1. 通过将NSURL实例作为根对象,调用+[NSKeyedArchiver archivedDataWithRootObject:]来写入任何非文件URL。
  2. ...

当使用-[NSUserDefaults URLForKey:]读取NSURL时,使用以下逻辑:

  1. 如果该键的值为NSData,则使用NSData作为参数调用+[NSKeyedUnarchiver unarchiveObjectWithData:]。如果NSData可以作为NSURL解档,则返回NSURL,否则返回nil。
  2. ...

因此,保存托管对象ID只需简单地执行以下操作:

NSUserDefaults.standardUserDefaults().setURL(object.objectID.URIRepresentation(),
                                             forKey: "selected")

例如,检索对象ID和对象可以像这样:

if let url = NSUserDefaults.standardUserDefaults().URLForKey("selected"),
    let oid = context.persistentStoreCoordinator!.managedObjectIDForURIRepresentation(url),
    let object = try? context.existingObjectWithID(oid) {

    print(object)
    // ...
}

如果您想要其他保存选定设置的方法,请参考上述评论


那么我该如何将URL/NSData转换回NSManagedObject? - Sweeper
1
@Paulw11已经在问题的评论中回答了那个问题。 - Wain
谢谢。我刚从晚餐回来,所以回复晚了。 :) - Sweeper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接