结合Coredata和Swiftui
#ios #swift #swiftui #coredata

最近,我必须使用 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逻辑保留在该结构中,但这取决于您。如果您想这样做 太好了,现在您可以在Views中创建,读取,更新和删除NSManagedObjects

提示 persistenceController here is an exemple)是Xcode在您使用'使用核心数据'选中选项。

与Coredata一起工作

要在View中使用Coredata操作,您需要访问NSManagedObjectContext。为此,您有两个选择:

  • 使用 @environment 在您的Views中包装器
@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中阅读。

警告:如果您添加,编辑或删除对象,则在Views之间传递所取的对象将破坏自动更新。 (如果您知道一种通过获取对象而不打破更新的方法,请告诉我,我将更新本指南)

因此,您需要在每个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>

要使用这些部分,您只需将它们传递到ListForEach,然后转到另一个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上。如果您喜欢这篇文章并想阅读其他人,请前往那儿。