Skip to main content

Command Palette

Search for a command to run...

SwiftUI应用CoreData小纸条(五)

运用CoreData的Delete Rule

Published
2 min read
SwiftUI应用CoreData小纸条(五)

SwiftUI应用CoreData小纸条(四)里我们为两个Entity建立了关系。我们需要利用这个关系做点关联的事。同时也利用SwiftUI应用CoreData小纸条(三) 中的万能View来快速构建查询结果。

构建Chapter和Topic列表

创建两个列表View

有了SwiftUI应用CoreData小纸条(三) 的FilteredList,我们建立两个列表View:

struct ChapterListView: View {
    var body: some View {
        FilteredList{ (item:Chapter) in
            NavigationLink{
                List{
                    Section(item.viewModel.name){
                        ForEach(item.viewModel.topics){topic in
                            Text(topic.viewModel.name)
                        }
                    }
                }
            }label: {
                let item = item.viewModel
                Text("\(item.name)")

            }
        }
    }
}

struct TopicListView: View {
    var body: some View {
        FilteredList{ (item:Topic) in
            NavigationLink{
                List{
                    let item = item.viewModel
                    Text(item.name)
                    if let chapter=item.chapter{
                        Text(chapter.viewModel.name)
                    }else{
                        Text("Not have Chapter")
                    }
                }
            }label: {
                let item = item.viewModel
                Text("\(item.name)")
            }
        }
    }
}

它们利用FilteredList建立了两个List(注意它们都支持左划删除),分别是没有任何查询条件的Chapter所有数据和Topic所有数据。每个条目点进去,都能看到与另一个Entity的关系。

更新ContentView

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Chapter.name, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Chapter>

    var body: some View {
        NavigationView {
            List{
                NavigationLink{
                    ChapterListView()
                }label: {
                    Text("ChapterList")
                }
                NavigationLink{
                    TopicListView()
                }label: {
                    Text("TopicList")
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
        }
    }

    private func addItem() {
        withAnimation {
            let count = items.count
            let newItem = Chapter(context: viewContext)
            newItem.name = "Chapter \(count)"

            for i in 1...3{
                let newTopic = Topic(context: viewContext)
                newTopic.name = "\(newItem.viewModel.name) topic \(i)"
                newItem.addToTopics(newTopic)
            }

            do {
                try viewContext.save()
            } catch {
                print(error.localizedDescription)
            }
        }
    }
}

如果我们点右上角的+,它会为我们增加一个Chapter,并同时为这个新增的Chapter加三个Topic。每个Topic的名字都是这样的Chapter id Topic id。我们做一个操作,点一下+,在Chapter里会多出一个Chapter 4,在Topic里会多出三个以Chapter 4为开头的Topic。然后我们再删除Chapter 4,再去看看Topic,会发现以Chapter 4为开头的Topic们还存在,而它们所对应的Chapter为nil。

delete_chapter.gif

Delete Rule

了解Delete Rule

删除规则决定了删除对象时它的关系怎么处理的行为。Core Data 提供了四种删除规则:

  • Nullify

置空模式。当关联对象被删除时,将对象设置为Null(nil)。这就是默认的状态了(上面的测试就是基于这种情况)。

  • No Action

无为模式。什么都不做。

  • Cascade

级联模式。当一个关联关系的记录被删除时,与它相关的所有条目都会删除。

  • Deny

拒绝模式。当关联关系的记录被删除时,与它相关的记录如果还有,会拒绝删除当前记录。

Delete Rule的设置在下图右侧的位置:

image.png

设置Cascade

在英语小助手中我希望的是删除一个Chapter就会把它下面的Topics都清除。哪么就需要在Chapter中的topics设置为Cascade,而Topic中的chapter则可以依然保持Nullify。

如果我们将Topic中的chapter关联也设置为Cascade会有什么情况呢?你也可以试一下,效果就是删除一个(注意是任意一个)Topic,CoreData会把它对应的Chapter记录删除,同时将其它的在这个Chapter中的Topic也统统删除。所以设置的时候要看清楚啊!

SwiftUI小纸条

Part 20 of 29

使用和书写SwiftUI过程中留下的各种小纸条

Up next

SwiftUI中使用Gesture绘图小纸条

使用Gesture和Path制作简易绘线

More from this blog

Https 本地服务器小纸条

最近想要尝试一下Telegram mini app,在调试时需要使用https的服务。试来试去发现在Mac下完成一个简单的HTTPS服务器还是需要点奇奇怪怪的工具的。但是整体来讲非常简单。 准备证书 主要会使用mkcert来创建证书。首先安装mkcert。 brew install mkcert brew install nss # if use Firefox 将mkcert加入到本地root CA。 mkcert -install 生成证书 本地调试可以使用localhost或127.0...

Feb 21, 20241 min read
Https 本地服务器小纸条

macOS中使用Docker发布一个python项目的小纸条

最近写了一个Telegram Bot,它可以使用语音和文字与GPT进行交互,成为了我日常重度使用的工具。从练习英语的听说读,到日常的搜索使用上都让我有了不少收获。终于,日常跑在我笔记本上的日子就要过去了,我需要它能日常跑在我的服务器上,所以准备使用Docker整个image,使得我日常的更新和服务器的迁移更为简单些。所以写下这个小纸条,方便以后自己回来查看。 安装Docker 使用Homebrew安装简单方便: brew install --cask docker Homebrew会视你的机器...

Mar 10, 20233 min read
macOS中使用Docker发布一个python项目的小纸条

老房东的纸条箱

39 posts