[SwiftUI 100天] Bookworm-part9 删除 Core Data 对象

2020/4/27 23:04:02

本文主要是介绍[SwiftUI 100天] Bookworm-part9 删除 Core Data 对象,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

译自 www.hackingwithswift.com/books/ios-s…
更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀

从一个 Core Data fetech request 中删除对象

我们已经使用了@FetchRequest来拉取 Core Data 对象到 SwiftUI 的List,再增加少量工作,我们就能启用轻扫删除和编辑/完成按钮。

就像常规的数据数组一样,大部分的工作是通过附加一个onDelete(perform:)modifier 给ForEach来实现的,不过相对于从数组中移除项,我们需要从 fetch 请求中找到请求的对象,然后对其调用我们的 managed object context 的delete()方法。一旦目标对象都删除完成,我们需要触发 context 的保存。如果不这么做,变更不会被实际写入磁盘。

把下面这个方法添加到ContentView

func deleteBooks(at offsets: IndexSet) {
    for offset in offsets {
        // find this book in our fetch request
        let book = books[offset]

        // delete it from the context
        moc.delete(book)
    }

    // save the context
    try? moc.save()
}复制代码

注意,onDelete(perform:)modifier 是附着在ForEach而不是List

添加下面这个 modifier:

.onDelete(perform: deleteBooks)复制代码

这样我们就获得了轻扫删除功能,我们可以更进一步,添加一个编辑/完成按钮。找到ContentViewnavigationBarItems()modifier ,修改成下面这样:

.navigationBarItems(leading: EditButton(), trailing: Button(action: {复制代码

这样就完成了ContentView,再次尝试运行应用 —— 你应该可以自由地添加和删除图书了,删除操作是通过轻扫手势或者编辑按钮来触发。

译自 www.hackingwithswift.com/books/ios-s…

用 alert 显示 NavigationLink

你已经了解如何使用NavigationLink跳转新的一屏,这个新视图可以某个自定义的视图或者 SwiftUI 的内置类型,比如Text或者Image。因为我们是处于一个NavigationView,iOS 自动提供了一个 “Back” 按钮,让用户可以返回之前一屏,它们也可以从屏幕的左边缘轻扫返回。不过,有的时候通过编程返回也是有用的。

为了演示这一点,我们要给我们的应用添加最后一个特性:删除用户正在看的书。做这个操作时,我们需要显示一个警告框,提示用户是否真的想要删除该书,得到肯定之后再从当前 managed object context 删除该书。一旦这个动作完成,停留在当前界面就没有意义了,因为关联的书已经不存在了。我们需要弹出当前视图 —— 将其从NavigationView栈顶移除,并且返回之前一屏。

首先,我们需要三个新的属性,放在DetailView结构体中:一个持有 Core Data managed object context (这样我们才能删除东西),一个持有 presentation mode(这样我们才能从导航栈中弹出视图),一个控制我们是否要显示确认警告的状态。

把下面三个属性添加到DetailView:

@Environment(\.managedObjectContext) var moc
@Environment(\.presentationMode) var presentationMode
@State private var showingDeleteAlert = false复制代码

第二步是写一个删除当前图书的方法,然后 dismiss 当前视图。至于这个视图是通过 navigation link 而不是 sheet 显示的这一点区别,我们仍然可以使用相同的presentationMode.wrappedValue.dismiss()代码。

把下面这个方法添加到DetailView

func deleteBook() {
    moc.delete(book)

    // uncomment this line if you want to make the deletion permanent
    // try? self.moc.save()
    presentationMode.wrappedValue.dismiss()
}复制代码

第三步是添加一个alert()modifier,关注showingDeleteAlert,内部展示一个Alert视图,询问用户确认动作。目前为止我们用过有一个 dimiss 按钮的简单 alert,这一回我们需要两个按钮:一个按钮删除图书,另一个取消。

SwiftUI 为这个用途提供两个专门的按钮:.destructive接收标题和 action 闭包,显示为红色,以便警告用户该操作将删除数据,.cancel()则会导致 alert 被 dismisse。 Apple 对于我们应该给 alert 文本取标签提供了明确的指引,让我在这里重申一下:如果只是简单如“我明白”,那么“OK”就是可以的,但假如你希望用户做出选择,那你应该避免像“Yes” 和 “No” 这样的标题,而应该使用像 “Ignore”,“Reply” 和 “Confirm” 这样的动词。

在这个案例中,我们将采用 “Delete”作为 destructive 按钮的标题,然后是一个.cancel()按钮,以便用户可以退出删除操作。把下面这个 modifier 添加到DetailViewGeometryReader

.alert(isPresented: $showingDeleteAlert) {
    Alert(title: Text("Delete book"), message: Text("Are you sure?"), primaryButton: .destructive(Text("Delete")) {
            self.deleteBook()
        }, secondaryButton: .cancel()
    )
}复制代码

最后一步是添加一个导航栏按钮,以启动删除过程 —— 它只做一件事,反转showingDeleteAlert布尔型,因为alert()modifier 已经在监控它。把下面这个 modifier 也添加到DetailViewGeometryReader

.navigationBarItems(trailing: Button(action: {
    self.showingDeleteAlert = true
}) {
    Image(systemName: "trash")
})复制代码

现在你可以在ContentView里使用轻扫或者编辑按钮来删除图书,或者在DetailView视图中点击专门的删除按钮完成同样的目标 —— 它会删除该书,更新ContentView列表,然后自动关闭当前细节视图。

又一个应用完成了 —— 干得漂亮!

我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~





这篇关于[SwiftUI 100天] Bookworm-part9 删除 Core Data 对象的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程