iOS 应用中的数据持久化

核心决策

选择能解决问题的最简单持久化方法。大多数应用不需要复杂的数据库。从简单开始,只有当您有特定原因时才增加复杂性。

UserDefaults:用于简单偏好设置

何时使用

设置、偏好、小型状态片段。切换开关、选择的主题、用户偏好。任何自然的键值对且大小在几 KB 以内的内容。

示例

// Save
UserDefaults.standard.set(true, forKey: "darkModeEnabled")

// Read
let isDarkMode = UserDefaults.standard.bool(forKey: "darkModeEnabled")

何时不该使用

不要存储大量数据。不要存储敏感信息(应使用 Keychain)。不要用于需要结构或关系的数据。UserDefaults 是一个字典——请像对待字典一样对待它。

Codable 与 FileManager:用于结构化数据

何时使用

当您有需要持久化的自定义类型时。任务列表、笔记、日志条目,以及任何可以放入内存的结构化数据。这通常是独立开发的最佳选择——实现简单快速,功能足以应对大多数场景。

示例

struct Note: Codable, Identifiable {
    let id: UUID
    var title: String
    var content: String
    var createdAt: Date
}

// Save
func saveNotes(_ notes: [Note]) {
    let encoder = JSONEncoder()
    if let encoded = try? encoder.encode(notes) {
        let url = getDocumentsDirectory().appendingPathComponent("notes.json")
        try? encoded.write(to: url)
    }
}

// Load
func loadNotes() -> [Note] {
    let url = getDocumentsDirectory().appendingPathComponent("notes.json")
    guard let data = try? Data(contentsOf: url) else { return [] }
    let decoder = JSONDecoder()
    return (try? decoder.decode([Note].self, from: data)) ?? []
}

func getDocumentsDirectory() -> URL {
    FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
}

优点

简单。无依赖。易于调试(JSON 文件易于阅读)。对版本控制友好。您可以打开文件查看确切存储的内容。迁移只需转换 JSON。

Core Data:用于复杂关系

何时使用

当您需要数据模型之间的关系时。当您需要高效查询数据子集时。当您处理无法放入内存的大型数据集时。当您需要内置的撤销/重做功能时。

何时不该使用

不要仅仅因为 Core Data 看起来“专业”就使用它。复杂性成本是真实的。如果您的数据可以放入内存且没有复杂的关系,Codable 与 FileManager 可能更简单。

现实检查

Core Data 有学习曲线。托管对象上下文、抓取请求、关系、迁移——这些都增加了复杂性。确保收益大于成本。对于许多独立应用来说,并不值得。

CloudKit:用于同步

何时使用

当用户需要在多个设备上访问数据时。当您想要同步而不想运行自己的服务器时。当您可以接受将 iCloud 生态系统作为必要条件时。

重要考虑因素

CloudKit 功能强大,但需要仔细处理错误。用户可能登出了 iCloud,存储空间可能不足,网络可能不可用。您的应用必须支持离线工作,并能优雅处理同步失败。这比听起来要复杂。

决策框架

从这里开始

  1. 仅仅是设置吗?使用 UserDefaults。
  2. 是可以放入内存的结构化数据吗?使用 Codable + FileManager。
  3. 需要复杂的查询或关系吗?考虑使用 Core Data。
  4. 需要跨设备同步吗?添加 CloudKit 或其他同步方案。

迁移路径

从简单开始。您以后随时可以迁移到更复杂的方案。从 Codable 转向 Core Data 需要工作,但并非不可逾越。为了“以防万一”而从第一天就开始使用 Core Data 会增加复杂性——而您可能永远不需要它。

实用提示

始终处理错误

文件保存可能会失败。磁盘可能会满。权限可能会被拒绝。请优雅地处理这些情况。至少要记录错误。更好的做法是:向用户显示清晰的信息并提供选项(重试、保存到其他地方等)。

频繁保存

在每次更改时或通过短定时器自动保存。永远不要要求用户手动保存。永远不要因为应用崩溃而丢失数据。保存的成本很低——丢失数据的代价很高。

测试数据丢失场景

在保存中途强行关闭应用。填满磁盘。在低存储空间下测试。将设备切换到飞行模式。您的持久化层应该在不丢失用户数据的情况下处理这些情况。

目标

用户永远不应该思考他们的数据是如何存储的。每当他们打开应用时,数据就应该可靠地出现在那里。这就是好的持久化所呈现的样子——隐形、可靠且实现简单。

需要在真实项目里做这些技术取舍?

数据持久化通常不是单独决策,而是 iOS 产品范围、性能与迭代节奏的一部分。Shawn Studio 可以在真实项目中一起梳理这些判断,并把它们落到可上线的实现上。