iOS17适配指南之SwiftData(二)

前文iOS17适配指南之SwiftData(一)使用 UIKit 对 SwiftData 进行了简单使用。其实 SwiftData 配合 SwiftUI 才是 Apple 的初心,因此本文以 SwiftUI 的视角进行 SwiftData 的使用讲解。

使用步骤

  1. 导入模块import SwiftData。
  2. 使用@Model修饰模型。
  3. 将模型注册到modelContainer。
  4. 获取模型上下文@Environment(\.modelContext) private var modelContext。
  5. 通过模型上下文进行增删改操作。
  6. 通过@Query修饰模型数组,获取查询的数据。

案例

swift 复制代码
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
        }
    }
}

效果

相关推荐
黑化旺仔2 小时前
【OC】Runtime:类元数据、加载初始化与消息派发
开发语言·macos·ios·objective-c
songgeb2 小时前
iOS App支持设置RTL语言的实践
ios·swift·ui kit
软泡芙3 小时前
【iOS】swift启动屏显示黑屏
ios
用户69371750013844 小时前
当你向领导申请 AI 编程工具预算时,如果领导追问“能提效多少,有量化数据吗”,你该怎么回答?
android·后端·ios
Layer4 小时前
一些脱离 Mac 依赖的 Agent 操作 iPhone 实现
ios·ai编程·测试
用户69371750013846 小时前
当我说 Claude 搭配 GLM-5.3-Flash 太好用了,同事却提醒我:你可能正在失去对代码的掌控
android·后端·ios
茶底世界之下6 小时前
一键裁方会丢掉什么?用 Awaking 给园林照片做两种画幅
ios
Marco_Marco1358 小时前
定位SDK接入实战:Android/iOS/鸿蒙三端怎么选、怎么接
android·ios·harmonyos
老李IT笔记1 天前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机
2501_915921431 天前
iOS应用耗电测试:使用Energy Log、Keymob和Instruments进行性能监控与能源消耗分析
android·ios·小程序·https·uni-app·iphone·webview