前文iOS17适配攻略之SwiftData(一)运用 UIKit 对 SwiftData 进行了简单运用。其实 SwiftData 合作 SwiftUI 才是 Apple 的初心,因而本文以 SwiftUI 的视角进行 SwiftData 的运用讲解。
运用过程
- 导入模块
import SwiftData
。 - 运用
@Model
润饰模型。 - 将模型注册到
modelContainer
。 - 获取模型上下文
@Environment(\.modelContext) private var modelContext
。 - 经过模型上下文进行增修正操作。
- 经过
@Query
润饰模型数组,获取查询的数据。
事例
import SwiftData
import SwiftUI
// MARK: - 模型,有必要是class
@Model
class TodoItem {
var title: String
var isCompleted: Bool
var date: Date
init(title: String = "", isCompleted: Bool = false, date: Date = .now) {
self.title = title
self.isCompleted = isCompleted
self.date = date
}
}
// MARK: - ContentView
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State private var path = [TodoItem]()
// 默许排序方法
@State private var sortOrder = SortDescriptor(\TodoItem.title)
var body: some View {
NavigationStack(path: $path) {
TodoListView(sort: sortOrder)
.navigationDestination(for: TodoItem.self) { todoItem in
EditView(todoItem: todoItem)
}
.navigationTitle("TodoList")
.toolbar {
// 增加数据
Button("Add", systemImage: "plus", action: addTodoItem)
// 修正排序方法
Menu("Sort", systemImage: "arrow.up.arrow.down") {
Picker("Sort", selection: $sortOrder) {
Text("Title")
.tag(SortDescriptor(\TodoItem.title, order: .reverse))
Text("Date")
.tag(SortDescriptor(\TodoItem.date, order: .reverse))
}
.pickerStyle(.inline)
}
}
}
}
// 1. 增加
func addTodoItem() {
let todoItem = TodoItem()
modelContext.insert(todoItem)
path = [todoItem]
}
}
// MARK: - TodoListView
struct TodoListView: View {
@Environment(\.modelContext) private var modelContext
// 4. 查询并排序
@Query private var todoItems: [TodoItem]
init(sort: SortDescriptor<TodoItem>) {
_todoItems = Query(sort: [sort])
}
var body: some View {
if todoItems.isEmpty {
ContentUnavailableView.search
} else {
List {
ForEach(todoItems) { todoItem in
NavigationLink(value: todoItem) {
HStack {
Text(todoItem.title)
Spacer()
Text(todoItem.date.formatted(.dateTime.locale(Locale(identifier: "zh_Hans_CN"))))
todoItem.isCompleted ? Image(systemName: "checkmark.square") : Image(systemName: "square")
}
}
}
.onDelete(perform: deletedTodoItem)
}
}
}
// 2. 删除
func deletedTodoItem(_ indexSet: IndexSet) {
indexSet.forEach { index in
let todoItem = todoItems[index]
modelContext.delete(todoItem)
}
}
}
// MARK: - EditView
struct EditView: View {
@Environment(\.modelContext) private var modelContext
@Bindable var todoItem: TodoItem
var body: some View {
Form {
// 3. 修正
TextField("请输入标题", text: $todoItem.title)
Toggle("是否完结", isOn: $todoItem.isCompleted)
DatePicker(selection: $todoItem.date) {
Text("时间")
}
.environment(\.locale, Locale(identifier: "zh_Hans_CN"))
}
.padding()
.navigationTitle("修改")
.navigationBarTitleDisplayMode(.inline)
}
}
@main
struct SwiftDataTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(for: TodoItem.self) // 注册模型到modelContainer
}
}
}
效果