第 14 章:构建一个小型应用
待办事项列表 (ToDo List)
项目概述
在本章中,我们将使用 SwiftData 构建一个完整的待办事项列表应用。该应用将涵盖以下核心功能:
- 创建、读取、更新和删除待办事项
- 标记任务完成状态
- 按日期或优先级排序任务
- 数据持久化与自动同步
1. 数据模型设计
import SwiftData
@Model
final class TodoItem {
var title: String
var isCompleted: Bool
var dueDate: Date?
var priority: Priority
enum Priority: Int, Codable, CaseIterable {
case low = 0, medium, high
}
init(title: String, isCompleted: Bool = false, dueDate: Date? = nil, priority: Priority = .medium) {
self.title = title
self.isCompleted = isCompleted
self.dueDate = dueDate
self.priority = priority
}
}
2. 设置 ModelContainer
在应用的入口点初始化容器:
import SwiftUI
@main
struct TodoApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: TodoItem.self)
}
}
3. 核心功能实现
添加新任务
struct AddTodoView: View {
@Environment(\.modelContext) private var context
@Environment(\.dismiss) private var dismiss
@State private var title = ""
@State private var dueDate = Date()
@State private var priority = TodoItem.Priority.medium
var body: some View {
Form {
TextField("任务标题", text: $title)
DatePicker("截止日期", selection: $dueDate)
Picker("优先级", selection: $priority) {
ForEach(TodoItem.Priority.allCases, id: \.self) {
Text($0.description)
}
}
Button("添加") {
let newItem = TodoItem(
title: title,
dueDate: dueDate,
priority: priority
)
context.insert(newItem)
dismiss()
}
}
}
}
任务列表视图
struct TodoListView: View {
@Query(sort: \TodoItem.dueDate) private var items: [TodoItem]
var body: some View {
List {
ForEach(items) { item in
TodoItemRow(item: item)
}
.onDelete(perform: deleteItems)
}
.toolbar {
Button("添加", systemImage: "plus") {
// 显示添加视图
}
}
}
private func deleteItems(_ indexSet: IndexSet) {
for index in indexSet {
let item = items[index]
context.delete(item)
}
}
}
任务状态切换
struct TodoItemRow: View {
@Bindable var item: TodoItem
var body: some View {
HStack {
Image(systemName: item.isCompleted ? "checkmark.circle.fill" : "circle")
.onTapGesture {
item.isCompleted.toggle()
}
VStack(alignment: .leading) {
Text(item.title)
.strikethrough(item.isCompleted)
if let dueDate = item.dueDate {
Text(dueDate.formatted())
.font(.caption)
}
}
Spacer()
PriorityBadge(priority: item.priority)
}
}
}
4. 高级功能实现
筛选与排序
enum TodoFilter: String, CaseIterable {
case all, completed, pending
}
struct TodoListView: View {
@State private var selectedFilter: TodoFilter = .all
@State private var sortOrder = [SortDescriptor(\TodoItem.dueDate)]
var body: some View {
let predicate = buildPredicate()
@Query(filter: predicate, sort: sortOrder) var filteredItems: [TodoItem]
// 列表实现...
Picker("筛选", selection: $selectedFilter) {
ForEach(TodoFilter.allCases, id: \.self) {
Text($0.rawValue)
}
}
.pickerStyle(.segmented)
}
private func buildPredicate() -> Predicate<TodoItem> {
switch selectedFilter {
case .all:
return #Predicate<TodoItem> { _ in true }
case .completed:
return #Predicate<TodoItem> { $0.isCompleted }
case .pending:
return #Predicate<TodoItem> { !$0.isCompleted }
}
}
}
5. 数据预览与测试
在 Xcode 预览中提供测试数据:
#Preview {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try! ModelContainer(for: TodoItem.self, configurations: config)
// 添加示例数据
for i in 1..<10 {
let item = TodoItem(
title: "任务 \(i)",
isCompleted: Bool.random(),
dueDate: Date().addingTimeInterval(Double.random(in: 0...86400*7)),
priority: TodoItem.Priority.allCases.randomElement()!
)
container.mainContext.insert(item)
}
return NavigationStack {
TodoListView()
}
.modelContainer(container)
}
6. 项目扩展建议
- 分类功能:为任务添加分类标签
- 提醒通知:使用 NotificationCenter 实现任务提醒
- 数据统计:显示任务完成情况的统计图表
- iCloud 同步:启用 CloudKit 实现跨设备同步
- Widget 支持:在主屏幕显示近期任务
7. 完整项目结构
TodoApp/
├── Models/
│ └── TodoItem.swift
├── Views/
│ ├── TodoListView.swift
│ ├── AddTodoView.swift
│ ├── TodoItemRow.swift
│ └── PriorityBadge.swift
├── Utilities/
│ └── PredicateBuilder.swift
└── TodoApp.swift
通过这个项目,您已经掌握了使用 SwiftData 构建完整应用的核心流程。接下来可以尝试实现笔记应用或联系人管理来巩固所学知识。
