由donnywals于2020年7月20日发布
在Xcode 12中,您可以创建不再使用AppDelegate和SceneDelegate来管理应用程序生命周期的项目,通常我们在AppDelegate中集成Core Data,相关步骤可以参考《iOS开发从入门到精通》课程的第七章节。 现在我们可以使用Swift的新@main注释,将符合App协议的结构转换为应用程序的主入口点。
在Xcode 12中创建新项目时,可以选择对SwiftUI项目使用SwiftUI App应用程序生命周期。
尽管Xcode 12 beta 5引入了在创建新项目时在SwiftUI应用程序中包含Core Data的选项,但是您可能已有一个不使用Core Data的现有SwiftUI项目。另外,您可能会很好奇您如何在SwiftUI项目中手动集成Core Data,因为Apple提供的新Core Data模板并没有什么神奇之处。
将核心数据添加到SwiftUI项目只需两个小步骤:
- 将Core Data模型文件添加到您的项目
- 初始化NSPersistentContainer
将Core Data模型文件添加到您的项目
要将新的Core Data模型文件添加到您的项目中,请选择File-> New-> File(cmd + N),然后从文件类型选择器的Core Data部分中选择Data Model。
选择此名称后,为您的模型选择一个名称。 Xcode用来选择的默认名称是项目的名称,但是您可以选择任何想要的名称。
我个人通常会以我的项目名称为名,除了觉得熟悉之外,因为它是Xcode在较早的Xcode版本中会选择的默认名称。当前,Xcode会为您选择的默认名称是Model,这也是一个很好的名称。
这就是全部。现在,您的核心数据模型文件已添加到您的项目中,可供NSPersistentContainer使用。
初始化NSPersistentContainer
从iOS 10开始,推荐使用和管理Core Data堆栈的方法是通过NSPersistentContainer。当Xcode为您生成Core Data实现时,它也会使用NSPersistentContainer。您可以在任何需要的地方初始化NSPersistentContainer。我将向您展示如何在App结构中将其初始化为属性,但是您也可以在专用数据源对象中初始化NSPersistentContainer。我建议不要从View内部初始化NSPersistentContainer,但是可以这样做。请记住,尽管只应加载一次容器。
让我们看一下实例化NSPersistentContainer所需的代码:
struct MyApplication: App {
let persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApplication")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
var body: some Scene {
WindowGroup {
Text("Hello, World!")
}
}
}
初始化持久性容器时,您要做的所有事情就是通过将模型名称传递给初始化程序来告诉它要加载哪个模型文件,然后在容器实例上调用loadPersistentStores。 完成此操作后,您的Core Data堆栈便已初始化并准备就绪。 在这里,您可以使用View中的@Environment属性包装器将容器的viewContext插入应用程序的环境中,也可以通过其他方式传递它。
请记住,您不必在App结构中初始化持久性容器。 您还可以创建一个PersistenceManager对象,例如:
class PersistenceManager {
let persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApplication")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
}
struct MyApplication: App {
let persistence = PersistenceManager()
var body: some Scene {
WindowGroup {
Text("Hello, World!")
}
}
}
这将完全正常。
AppDelegate中生成的Core Data堆栈的旧版本包含一项额外功能,该功能可以在应用程序进入后台时自动保存所有更改。 您可以通过侦听NotificationCenter.default上的UIApplication.willResignActiveNotification来模仿此行为。
请注意,Apple的用于SwiftUI应用程序的新Core Data模板也缺少此自动保存功能。
不幸的是,我还没有找到一种从App结构中订阅此通知的方法,因为它是一个结构,并且使用基于闭包的侦听器抱怨访问持久性容器时捕获了一个可变的self参数。
解决此问题的最简单方法是在专门的PersistenceManager中进行订阅,就像我之前向您展示的那样:
class PersistenceManager {
let persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApplication")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
init() {
let center = NotificationCenter.default
let notification = UIApplication.willResignActiveNotification
center.addObserver(forName: notification, object: nil, queue: nil) { [weak self] _ in
guard let self = self else { return }
if self.persistentContainer.viewContext.hasChanges {
try? self.persistentContainer.viewContext.save()
}
}
}
}
这样一来,您应该拥有在SwiftUI 2.0应用程序中开始使用Core Data所需的所有信息。
总结
在本周的帖子中,我向您展示了如何从应用程序中的任何位置初始化Core Data,使您可以在SwiftUI 2.0的新应用程序生命周期中使用它。
您已经看到将核心数据添加到您的应用程序所需要做的全部工作,就是创建模型文件并初始化NSPersistentContainer对象。 它可以在您的应用程序中的任何位置运行,包括使用基于旧AppDelegate的应用程序生命周期的应用程序。
译自:https://www.donnywals.com/using-core-data-with-swiftui-2-0-and-xcode-12/