如何持久存储 NSManagedObjectID?
How to store a NSManagedObjectID persistently?
为避免成为 XY 问题,这里有一些背景知识:
我的应用程序允许用户创建和保存很多设置,有点像 Xcode 的字体和颜色选择器:
这是因为用户可以设置很多东西。只需点击保存的设置而不是重新设置所有这些设置会更容易。
我使用 Core Data 来存储用户保存的设置。用户创建的每个设置都是 NSManagedObject
子类的一个实例。现在我需要永久存储所选设置,以便用户在重新打开应用程序时选择与之前相同的设置。
我的第一个想法是将 NSManagedObject
子类实例存储在 NSUserDefaults
中。但是根据文档,除非将其转换为 NSData
:
否则我无法存储它
A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.
然后我尝试存储 NSManagedObject
子类实例的 objectID
。我看到有一个 URIRepresentation()
方法 returns 和 NSURL
。所以我认为这会起作用:
NSData(contentsOfURL: selectedOption!.objectID.URIRepresentation())
但是初始化程序不知何故失败了。
现在我意识到这是一个愚蠢的想法,因为即使我可以将它转换为 NSData
,我也无法将 NSData
转换回 NSManagedObjectID
!
根据 this question,OP 似乎能够存储对象 ID:
I store the selected theme objectID in NSUserDefaults so that when the app restarts, the selected theme will still be intact.
我该怎么做?
NSUserDefaults
有 "convenience methods"
public func setURL(url: NSURL?, forKey defaultName: String)
public func URLForKey(defaultName: String) -> NSURL?
允许存储和检索 NSURL
就像获得的一样
通过 URIRepresentation()
。与 NSData
之间的转换
透明处理。来自 documentation:
When an NSURL is stored using -[NSUserDefaults setURL:forKey:]
, some adjustments are made:
- Any non-file URL is written by calling
+[NSKeyedArchiver archivedDataWithRootObject:]
using the NSURL instance as the root
object.
- ...
When an NSURL is read using -[NSUserDefaults URLForKey:]
, the following logic is used:
- If the value for the key is an NSData, the NSData is used as the argument to
+[NSKeyedUnarchiver unarchiveObjectWithData:]
. If the NSData can be unarchived as an NSURL, the NSURL is returned otherwise nil is returned.
- ...
因此保存托管对象 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)
// ...
}
有关保存所选设置的替代方法,请参阅 。
为避免成为 XY 问题,这里有一些背景知识:
我的应用程序允许用户创建和保存很多设置,有点像 Xcode 的字体和颜色选择器:
这是因为用户可以设置很多东西。只需点击保存的设置而不是重新设置所有这些设置会更容易。
我使用 Core Data 来存储用户保存的设置。用户创建的每个设置都是 NSManagedObject
子类的一个实例。现在我需要永久存储所选设置,以便用户在重新打开应用程序时选择与之前相同的设置。
我的第一个想法是将 NSManagedObject
子类实例存储在 NSUserDefaults
中。但是根据文档,除非将其转换为 NSData
:
A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.
然后我尝试存储 NSManagedObject
子类实例的 objectID
。我看到有一个 URIRepresentation()
方法 returns 和 NSURL
。所以我认为这会起作用:
NSData(contentsOfURL: selectedOption!.objectID.URIRepresentation())
但是初始化程序不知何故失败了。
现在我意识到这是一个愚蠢的想法,因为即使我可以将它转换为 NSData
,我也无法将 NSData
转换回 NSManagedObjectID
!
根据 this question,OP 似乎能够存储对象 ID:
I store the selected theme objectID in NSUserDefaults so that when the app restarts, the selected theme will still be intact.
我该怎么做?
NSUserDefaults
有 "convenience methods"
public func setURL(url: NSURL?, forKey defaultName: String)
public func URLForKey(defaultName: String) -> NSURL?
允许存储和检索 NSURL
就像获得的一样
通过 URIRepresentation()
。与 NSData
之间的转换
透明处理。来自 documentation:
When an NSURL is stored using
-[NSUserDefaults setURL:forKey:]
, some adjustments are made:
- Any non-file URL is written by calling
+[NSKeyedArchiver archivedDataWithRootObject:]
using the NSURL instance as the root object.- ...
When an NSURL is read using
-[NSUserDefaults URLForKey:]
, the following logic is used:
- If the value for the key is an NSData, the NSData is used as the argument to
+[NSKeyedUnarchiver unarchiveObjectWithData:]
. If the NSData can be unarchived as an NSURL, the NSURL is returned otherwise nil is returned.- ...
因此保存托管对象 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)
// ...
}
有关保存所选设置的替代方法,请参阅