第 14 章:构建一个小型应用
笔记应用 (Note App)
项目概述
本节将指导你使用 SwiftData 构建一个功能完整的笔记应用,包含以下核心功能:
- 创建/编辑/删除笔记
- 富文本内容支持(标题+正文)
- 分类标签管理
- 搜索功能
- 数据持久化与自动同步
1. 数据模型设计
@Model
final class Note {
var title: String
var content: String
var createdAt: Date
var updatedAt: Date
var isPinned: Bool
@Relationship(deleteRule: .nullify) var tags: [Tag]
init(title: String, content: String) {
self.title = title
self.content = content
self.createdAt = .now
self.updatedAt = .now
self.isPinned = false
}
}
@Model
final class Tag {
var name: String
var notes: [Note]
init(name: String) {
self.name = name
}
}
2. 核心功能实现
初始化 ModelContainer
struct NotesApp: App {
let container = ModelContainer(
for: [Note.self, Tag.self],
configurations: ModelConfiguration(isStoredInMemoryOnly: false)
)
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(container)
}
}
笔记列表视图
struct NotesListView: View {
@Query(sort: \Note.updatedAt, order: .reverse) var notes: [Note]
@Environment(\.modelContext) private var context
var body: some View {
List {
ForEach(notes) { note in
NavigationLink {
NoteEditorView(note: note)
} label: {
VStack(alignment: .leading) {
Text(note.title).font(.headline)
Text(note.content.prefix(50)).font(.subheadline)
}
}
}
.onDelete { indexes in
indexes.forEach { index in
context.delete(notes[index])
}
}
}
.toolbar {
Button("Add") {
let newNote = Note(title: "New Note", content: "")
context.insert(newNote)
}
}
}
}
笔记编辑器
struct NoteEditorView: View {
@Bindable var note: Note
@State private var newTagName = ""
var body: some View {
Form {
TextField("Title", text: $note.title)
TextEditor(text: $note.content)
.frame(minHeight: 200)
Section("Tags") {
ForEach(note.tags) { tag in
Text(tag.name)
}
HStack {
TextField("Add Tag", text: $newTagName)
Button("Add") {
let tag = Tag(name: newTagName)
note.tags.append(tag)
newTagName = ""
}
}
}
}
.onDisappear {
note.updatedAt = .now
}
}
}
3. 高级功能扩展
搜索实现
@Query var allNotes: [Note]
func searchNotes(_ text: String) -> [Note] {
guard !text.isEmpty else { return allNotes }
let predicate = #Predicate<Note> { note in
note.title.localizedStandardContains(text) ||
note.content.localizedStandardContains(text)
}
return (try? allNotes.filter(predicate)) ?? []
}
自动保存策略
// 在 App 启动时设置自动保存
.container = ModelContainer(
for: Note.self,
configurations: ModelConfiguration(
isAutosaveEnabled: true
)
)
4. 项目优化建议
性能优化:
- 对长内容笔记实现分页加载
- 使用
@Query的animation参数实现平滑过渡
用户体验:
- 添加 Markdown 预览功能
- 实现笔记版本历史(需扩展数据模型)
数据安全:
- 添加本地加密功能(对
Data类型属性使用加密转换) - 实现回收站机制(软删除模式)
- 添加本地加密功能(对
5. 完整项目结构建议
NotesApp/
├── Models/
│ ├── Note.swift
│ └── Tag.swift
├── Views/
│ ├── NotesListView.swift
│ ├── NoteEditorView.swift
│ └── TagManagerView.swift
├── Utilities/
│ ├── SearchUtility.swift
│ └── AutoSaver.swift
└── NotesApp.swift
下一步挑战
尝试为应用添加以下功能:
- 笔记导出为 PDF 功能
- 基于标签的智能文件夹
- 与 CloudKit 的同步集成
- 多设备间的手势冲突解决
