最近,我必须使用 swiftui 和 coredata 。
构建一个应用程序
我以为Coredata几乎被用Uikit所使用,但显然有一些差异。
本指南旨在作为我使用Coredata与Swiftui结合的经验的摘要。如果我会找到其他方面,我会将它们添加到本指南中。
因此,事不宜迟,让我们开始。
设置
这是一个非常简单的部分。
- 如果您启动了一个新项目,则可以检查'使用核心数据'选项和' host in CloudKit '如果要将用户数据保存到云中。在这种情况下,Xcode将为您设置项目。 (因为CloudKit部分将需要执行一些额外的步骤)。
- 如果您已经有一个项目,则需要创建 persistence.swift 文件和一个Swift文件,您可以在其中初始化Coredata堆栈。 (您甚至可以按照上一步创建一个新项目,然后复制Xcode生成的 persistence.swift 文件。
设置@main应用程序
现在您有了项目,才能在View
中使用Coredata,您需要将managedObjectContext
传递给您的层次结构。
通常这是在您的 app.swift 文件中完成的。
@main
struct ExampleApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(persistenceController)
.environment(\\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
我个人通过,作为.environmentObject
, persistenceController 本身。因为我喜欢将所有CRUD逻辑保留在该结构中,但这取决于您。如果您想这样做
太好了,现在您可以在View
s中创建,读取,更新和删除NSManagedObjects
。
提示: persistenceController (here is an exemple)是Xcode在您使用'使用核心数据'选中选项。
与Coredata一起工作
要在View
中使用Coredata操作,您需要访问NSManagedObjectContext
。为此,您有两个选择:
- 使用 @environment 在您的
View
s中包装器
@Environment(\\.managedObjectContext) private var viewContext
- 使用 @environmentObject 包装器获取控制器,从中可以访问
viewContext
或crud方法
@EnvironmentObject private var persistenceController: PersistenceController
保存上下文
您可以使用NSManagedObjectContext
的.save()
方法保存上下文。保存上下文之前,您可以检查是否有一些更改,并仅在存在时保存它。
do {
if container.viewContext.hasChanges {
try container.viewContext.save()
}
} catch {
print(error)
}
保存对象
要保存NSManagedObject
,您首先需要实施它并配置其属性。然后保存上下文。
let note = Note(context: container.viewContext)
note.id = id
note.text = text
note.folder = folder
note.creationDate = Date()
saveContext()
提示:您可以在Swiftui的
withAnimation
函数中包装此代码动画。
获取对象
现在是提取部分,这是我发现最大困难的地方。让我们立即开始。
在SwiftUi中获取最方便的方法是使用 @fetchrequest 或 @sectionedfetchrequest 包装器,在每一个View
中,您都需要从CoreData中阅读。
警告:如果您添加,编辑或删除对象,则在
View
s之间传递所取的对象将破坏自动更新。 (如果您知道一种通过获取对象而不打破更新的方法,请告诉我,我将更新本指南)
因此,您需要在每个View
中添加 @fetchrequest ,您需要Coredata对象和自动更新。我知道这有点烦人,但值得。
因此,这样说的代码如下:
@FetchRequest(entity: Object.entity(),
sortDescriptors: [NSSortDescriptor],
predicate: NSPredicate,
animation: .default)
var objects: FetchedResults<Object>
或,如果您希望将对象按属性分组:
@SectionedFetchRequest(entity: Object.entity(),
sectionIdentifier: \\Object.property,
sortDescriptors: [NSSortDescriptor],
predicate: NSPredicate,
animation: .default)
var sections: SectionedFetchResults<YourSectionType, Object>
要使用这些部分,您只需将它们传递到List
或ForEach
,然后转到另一个ForEach
。
List(sections) { section in
Section(section.id) {
ForEach(section) { object in
// Configure your view with the object
}
}
}
提示:如果您使用 @sectionedfetchrequest 进行排序,则可能需要指定两个排序描述符。第一个将对部分进行分类,第二部分将负责每个部分内部的对象。此功能确实很有用,需要很少的努力。
使用 @fetchrequest 或 @sectionedfetchrequest 在添加,更新或删除对象时,视图将自动更新。
现在,如果您需要使用 @fetchrequest 与NSPredicate
一起使用,该NSPredicate
的参数从parent View
传递,我发现下一个选项非常有效。
@FetchRequest
var objects: FetchedResults<Object>
init(id: ID) {
_objects = FetchRequest<Object>(predicate: NSPredicate(format: "id == %@", id))
}
这样,您可以在init
中传递参数,并在保持自动更新的同时使用它来过滤结果。 @sectionedfetchrequest 。
更新对象
要更新NSManagedObject
,您将需要让NSManagedObject
更新,如前所述并更新其属性。然后保存上下文。
note.text = newText
note.folder = newFolder
saveContext()
删除对象
要删除NSManagedObject
,您需要将NSManagedObject
进行更新,如前所述并删除。
viewContext.delete(object)
我没有解释过每种Cordata的CRUD方法,例如批处理插入和删除,因为本指南专注于Coredata和Swiftui之间的相互作用。每个NSManagedObjectContext
方法,背景上下文,performandawait,行为与Uikit完全一样。
结论
这就是我到目前为止发现的关于 coreda 与 swiftui 一起使用的。本指南将不断更新。
如果您想提出一种更好的做事方式,请留下评论,我将使用最佳选择更新本指南。
我希望我能帮助您与Swiftui和iOS开发一起旅行。
在下一个指南中见!
如果您想支持我的工作并查看本指南,请查看BrainDump - Notes & Writing
谢谢你ð
Swiftylion
本文最初发表在SwiftyLion上。如果您喜欢这篇文章并想阅读其他人,请前往那儿。