第 12 章:错误处理与鲁棒性
用户体验:错误提示与恢复策略
1. 错误提示设计原则
- 清晰明确:错误信息应避免技术术语,用用户能理解的语言描述问题
- 上下文相关:在错误发生的界面直接提示,而非全局弹窗
- 可操作建议:提供明确的恢复选项(如"重试"、"取消"或引导至设置)
// 示例:SwiftUI 中的错误提示实现
.alert("保存失败", isPresented: $showError) {
Button("重试") { retrySave() }
Button("取消", role: .cancel) { }
} message: {
Text("无法保存您的更改,请检查网络连接后重试。")
}
2. 常见错误场景与处理策略
2.1 持久化失败
- 检测方法:捕获
ModelContext.save()抛出的错误 - 恢复策略:
- 自动重试机制(指数退避算法)
- 提供手动保存按钮
- 临时保存到内存或UserDefaults
do {
try modelContext.save()
} catch let error as NSError {
if error.domain == NSCocoaErrorDomain {
switch error.code {
case NSManagedObjectValidationError:
// 处理数据验证错误
case NSPersistentStoreSaveError:
// 处理存储错误
default: break
}
}
}
2.2 并发冲突
- 检测方法:
NSMergeConflict错误 - 恢复策略:
- 显示冲突内容对比界面
- 提供"保留我的更改"/"使用服务器版本"选项
- 实现自定义合并策略
3. 用户状态保存与恢复
- 自动保存草稿:定期自动保存未提交的修改
- 操作历史栈:实现撤销/重做功能
// 实现简单的撤销管理
Button(action: {
modelContext.undoManager?.undo()
}) {
Label("撤销", systemImage: "arrow.uturn.backward")
}
.disabled(!(modelContext.undoManager?.canUndo ?? false))
4. 防御性编程技巧
- 数据预验证:在保存前检查字段有效性
- 空状态处理:为可能为nil的关系提供占位UI
- 批量操作保护:限制单次操作的数据量
5. 错误日志与反馈机制
- 结构化日志:记录错误上下文信息
import os.log
let logger = Logger(subsystem: "com.yourapp.datastore", category: "persistence")
logger.error("Save failed: \(error.localizedDescription, privacy: .public)")
- 用户反馈通道:集成"报告问题"功能,自动附加相关日志
6. 无障碍考虑
- 为视觉障碍用户提供语音提示错误
- 确保错误提示可通过辅助技术访问
- 错误界面满足颜色对比度要求
7. 国际化与本地化
- 所有错误信息使用
LocalizedStringKey - 包含数字/日期等变量的错误信息使用
String.localizedStringWithFormat - 为不同文化提供适当的恢复操作排序
通过以上策略,可以构建既健壮又用户友好的SwiftData应用程序,在出现问题时保持用户体验的连贯性和可控性。
