我有一个swift应用程序,它使用核心数据来存储文档。每个文档包含一个实体Settings
,其中每个文档中只存在一个该实体的实例。
应为每个新文档自动创建实例,并且在打开现有文档时可以访问该实例。
我应该如何实施这样的核心数据应用程序?
答案 0 :(得分:0)
实现此类单例实体的最可靠方法是使用特殊的getter,在需要时检查并创建实体。
class Document: NSPersistentDocument {
var settings: Settings {
if _settings == nil {
do {
let fetchSettings = NSFetchRequest(entityName: "Settings")
let settingsList = try self.managedObjectContext!.executeFetchRequest(fetchSettings)
precondition(settingsList.count < 2, "Too many settings object in the core data store.")
if settingsList.count == 1 {
self._settings = settingsList[0] as? Settings
precondition(self._settings != nil)
} else {
self._settings = NSEntityDescription.insertNewObjectForEntityForName("Settings", inManagedObjectContext: self.managedObjectContext!) as? Settings
precondition(self._settings != nil)
// init the settings object here
self.managedObjectContext!.processPendingChanges()
self.managedObjectContext!.undoManager!.removeAllActions()
}
} catch {
preconditionFailure("Could not retrieve/create settings object because of an unknown core data error.")
}
}
return _settings!
}
private var _settings: Settings?
// ...
}
此示例中的类Settings
是NSManagedObject
的子类,用于简化对对象值的访问。您可以直接使用NSManagedObject
而不是自己的类。
类Document
有一个私有属性_settings
,它包含Settings
实体的当前实例。 getter settings
检查此变量,如果未设置实例,则检查该实体的托管对象上下文。
let fetchSettings = NSFetchRequest(entityName: "Settings")
let settingsList = try self.managedObjectContext!.executeFetchRequest(fetchSettings)
首先,从上下文中获取所有Settings
个实体的列表。
if settingsList.count == 1 {
self._settings = settingsList[0] as? Settings
precondition(self._settings != nil)
} else {
如果已存在Settings
实体,则会检查此列表。在这种情况下,使用现有实体。
self._settings = NSEntityDescription.insertNewObjectForEntityForName("Settings", inManagedObjectContext: self.managedObjectContext!) as? Settings
precondition(self._settings != nil)
// init the settings object here
如果不存在Settings
实体,则会创建一个新实体并使用默认值进行初始化。
self.managedObjectContext!.processPendingChanges()
self.managedObjectContext!.undoManager!.removeAllActions()
这两行删除了初始化新Settings
实体时创建的所有撤消操作。有必要确保新文档不以“已编辑”标志开头。它还确保初始撤消不会删除创建的Settings
对象。
在完成任何用户交互之前,务必尽快访问settings
属性。否则,界面将出现撤消操作的问题。最好是访问文档窗口settings
的{{1}}属性中的document
getter:
NSWindowController
override var document: AnyObject? {
didSet {
// access the `settings` property of the document.
}
}
?可以在Document.init()
方法中初始化文档的数据,但此时托管对象上下文仍为空。您必须等到文档初始化完成后才能检查托管对象上下文中是否存在init()
对象。
这实际上取决于应用程序的其余实现。但是很容易使用这样的代码:
Settings