第13章:最佳实践与设计模式
代码组织与模块化
1. 分层架构设计
// 推荐的项目结构示例
MyApp/
├── Models/ // SwiftData模型定义
│ ├── Todo.swift
│ ├── User.swift
│ └── Category.swift
├── Services/ // 数据服务层
│ ├── DataManager.swift // ModelContext统一管理
│ └── SyncService.swift
├── ViewModels/ // 业务逻辑层
│ ├── TodoViewModel.swift
│ └── UserViewModel.swift
└── Views/ // 表现层
├── TodoListView.swift
└── UserProfileView.swift
2. 模型定义规范
- 独立文件原则:每个
@Model模型应单独存放在Models/目录下 - 命名约定:
- 模型类使用单数名词(如
TodoItem而非TodoItems) - 关系属性使用复数形式(如
var items: [TodoItem])
- 模型类使用单数名词(如
// Models/Todo.swift 示例
@Model
final class Todo {
var title: String
var isCompleted: Bool
var dueDate: Date?
@Relationship(deleteRule: .nullify) var category: Category?
init(title: String) {
self.title = title
self.isCompleted = false
}
}
3. 数据访问抽象
建议通过协议抽象数据访问层,便于测试和替换实现:
// Services/TodoRepositoryProtocol.swift
protocol TodoRepository {
func fetchTodos(predicate: Predicate<Todo>?) async throws -> [Todo]
func createTodo(title: String) throws -> Todo
func deleteTodo(_ todo: Todo) throws
}
// Services/TodoDataService.swift
class TodoDataService: TodoRepository {
private let context: ModelContext
init(context: ModelContext) {
self.context = context
}
func fetchTodos(predicate: Predicate<Todo>?) async throws -> [Todo] {
let descriptor = FetchDescriptor<Todo>(predicate: predicate)
return try context.fetch(descriptor)
}
// ...其他实现...
}
4. 依赖注入模式
推荐使用环境对象传递ModelContext:
// 在应用入口初始化
@main
struct MyApp: App {
let container = ModelContainer(for: Todo.self)
var body: some Scene {
WindowGroup {
ContentView()
.modelContainer(container)
}
}
}
// 在子视图中获取
struct TodoListView: View {
@Environment(\.modelContext) private var context
@Query private var todos: [Todo]
var body: some View {
List(todos) { todo in
Text(todo.title)
}
}
}
5. 模块化建议
功能模块化:将相关模型和服务打包为独立Swift Package
// Package.swift .target( name: "TodoFeature", dependencies: [.product(name: "SwiftData", package: "swift-data")] )预编译模型:对于大型项目,可预编译Schema:
xcrun swiftdata-compiler generate Models/ --output CompiledSchema.swift测试模块隔离:为测试目标创建内存存储配置
func testContext() throws -> ModelContext { let config = ModelConfiguration(isStoredInMemoryOnly: true) let container = try ModelContainer(for: Todo.self, configurations: config) return ModelContext(container) }
6. 代码组织检查清单
| 最佳实践 | 实施建议 |
|---|---|
| 单一职责 | 每个文件/类只负责一个明确的功能 |
| 依赖清晰 | 使用import语句明确模块依赖 |
| 可测试性 | 通过协议抽象核心功能 |
| 可扩展性 | 预留扩展点(如extension Todo: CustomDebugStringConvertible) |
| 文档完整 | 为公开API添加文档注释(///) |
