在 iOS 开发中,数据持久化是一项极其重要的功能,用于保存数据以便用户在重新启动应用时仍然可以使用或访问之前的数据内容。根据开发需求和数据复杂度,iOS 提供了多种持久化方案。以下是目前 iOS 开发中常用的持久化方法及其适用场景:
1. UserDefaults #
用途:
用于存储轻量级的键值对数据,如用户偏好设置、简单的状态保存等。
特点:
基于键值存储,只支持简单的值类型(如
Int
、String
、Bool
、Array
、Dictionary
等)。数据量较小时性能良好,不适合存储大数据。
默认会将数据存储在沙盒中,随时可用。
适用场景:
保存用户偏好设置,比如主题模式(浅色/深色)。
存储会话状态,例如首次启动标志(类似
isFirstLaunch
)。代码示例:
// 保存数据
UserDefaults.standard.set(true, forKey: "isLoggedIn")
UserDefaults.standard.set("Dark", forKey: "themeMode")
// 读取数据
let isLoggedIn = UserDefaults.standard.bool(forKey: "isLoggedIn")
let themeMode = UserDefaults.standard.string(forKey: "themeMode") ?? "Light"
2. Keychain #
用途:
用于存储敏感信息(如密码、密钥、令牌)等需要安全保护的数据。
特点:
使用加密技术对存储内容进行保护。
即使应用被删除,存储在 Keychain 的数据仍然可用(除非你手动删除 Keychain 数据)。
适用场景:
存储身份验证数据,例如 OAuth Token 和用户的用户名、密码。
存储 API Key 或加密密钥。
代码示例(通过系统库实现):
import Security
func saveToKeychain(value: String, forKey key: String) {
let data = value.data(using: .utf8)!
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data]
SecItemAdd(query as CFDictionary, nil)
}
func getFromKeychain(forKey key: String) -> String? {
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: kCFBooleanTrue!,
kSecMatchLimit as String: kSecMatchLimitOne]
var result: AnyObject?
SecItemCopyMatching(query as CFDictionary, &result)
return (result as? Data).flatMap { String(data: $0, encoding: .utf8) }
}
3. 文件存储(File Handling) #
用途:
用于存储自定义文件数据,比如 JSON 文件、文本文件、图片、音频等。
特点:
灵活,适合存储二进制数据或大文件。
读取和写入都需要手动管理文件路径及数据流。
适用场景:
缓存图片、音频文件等大数据内容。
保存用户文档。
代码示例:
// 获取沙盒目录
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent("data.json")
// 写入文件
let jsonString = "{\"key\":\"value\"}"
try? jsonString.write(to: fileURL, atomically: true, encoding: .utf8)
// 读取文件
if let data = try? String(contentsOf: fileURL, encoding: .utf8) {
print("Read from file: \(data)")
}
4. SQLite #
用途:
使用轻量级关系型数据库存储和管理结构化数据。
特点:
更适合存储和查询结构化数据。
数据以表格和行的方式存储,支持复杂的 SQL 查询。
需要手动创建与管理表。
适用场景:
存储简单的关系型数据,比如订单信息、用户任务列表。
需要用数据库进行复杂查询。
代码示例(使用 SQLite.swift 第三方库):
import SQLite
// 创建数据库连接
let db = try Connection("path/to/database.sqlite3")
// 创建表
let users = Table("users")
let id = Expression<Int64>("id")
let name = Expression<String>("name")
try db.run(users.create { t in
t.column(id, primaryKey: true)
t.column(name)
})
// 插入数据
let insert = users.insert(name <- "John")
try db.run(insert)
// 查询数据
for user in try db.prepare(users) {
print("user: \(user[id]), name: \(user[name])")
}
5. Core Data #
用途:
Apple 官方提供的 ORM(对象关系映射)框架,用于管理复杂对象图并持久化。
特点:
可以轻松处理对象关系和状态追踪。
自动支持 CRUD 和数据持久化。
支持 iCloud 同步。
适用场景:
当需要存储复杂的数据模型(带关系)或对复杂查询有需求时。
代码示例(新增和查询数据):
import CoreData
// 获取上下文
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// 插入数据
let newUser = User(context: context)
newUser.id = UUID()
newUser.name = "Alice"
try context.save()
// 查询数据
let fetchRequest = NSFetchRequest<User>(entityName: "User")
let users = try context.fetch(fetchRequest)
for user in users {
print("User Name: \(user.name ?? "")")
}
6. Realm #
用途:
第三方数据库,专注于性能和易用性,适用于复杂模型和小型结构化数据。
特点:
无需手写 SQL,提供面向对象的数据存储方式。
高效的查询和存储性能。
自动管理对象的生命周期。
适用场景:
需要性能高效、管理数据模型简单的情况下。
代码示例:
import RealmSwift
// 定义模型
class User: Object {
@Persisted var id: UUID = UUID()
@Persisted var name: String = ""
}
// 插入数据
let realm = try! Realm()
let user = User()
user.name = "Alice"
try! realm.write {
realm.add(user)
}
// 查询数据
let users = realm.objects(User.self)
for user in users {
print("User Name: \(user.name)")
}
7. CloudKit #
用途:
将数据存储在 iCloud 中,实现跨设备同步和云共享。
特点:
Apple 提供的云服务,支持私有(用户数据)和公有(共享数据)存储。
数据可以同步到多个设备。
适用场景:
构建需要多设备数据同步的客户端。
代码示例:
import CloudKit
let container = CKContainer.default()
let privateDatabase = container.privateCloudDatabase
// 插入数据
let record = CKRecord(recordType: "User")
record["name"] = "Alice" as CKRecordValue
privateDatabase.save(record) { (record, error) in
if let error = error {
print("Error saving record: \(error)")
} else {
print("Record saved successfully!")
}
}
总结:常用场景选择 #
存储方案 | 适用场景 |
UserDefaults | 存储简单的用户偏好设置或状态 |
Keychain | 存储敏感信息(如密码、令牌) |
文件存储 | 存储文档、文件、音频、图片等 |
SQLite | 存储关系型结构化数据 |
Core Data | 复杂的数据模型及关系 |
Realm | 简单快速的本地数据库 |
CloudKit | 跨设备多用户的云存储和同步 |