前文iOS17适配指南之SwiftData(一)使用 UIKit 对 SwiftData 进行了简单使用。其实 SwiftData 配合 SwiftUI 才是 Apple 的初心,因此本文以 SwiftUI 的视角进行 SwiftData 的使用讲解。
使用步骤
- 导入模块
import SwiftData
。 - 使用
@Model
修饰模型。 - 将模型注册到
modelContainer
。 - 获取模型上下文
@Environment(.modelContext) private var modelContext
。 - 通过模型上下文进行增删改操作。
- 通过
@Query
修饰模型数组,获取查询的数据。
案例
代码语言:javascript复制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
}
}
}
效果
SwiftUI SwiftData.gif