数据持久化 #
一、持久化概述 #
Swift提供了多种数据持久化方案,适用于不同的场景。
1.1 持久化方案 #
| 方案 | 适用场景 | 特点 |
|---|---|---|
| UserDefaults | 简单配置 | 轻量、快速 |
| FileManager | 文件存储 | 灵活、通用 |
| CoreData | 复杂数据 | 强大、关系型 |
| Keychain | 敏感数据 | 安全、加密 |
二、UserDefaults #
2.1 基本用法 #
swift
let defaults = UserDefaults.standard
defaults.set("张三", forKey: "userName")
defaults.set(25, forKey: "userAge")
defaults.set(true, forKey: "isLoggedIn")
let userName = defaults.string(forKey: "userName") ?? ""
let userAge = defaults.integer(forKey: "userAge")
let isLoggedIn = defaults.bool(forKey: "isLoggedIn")
print(userName)
print(userAge)
print(isLoggedIn)
2.2 存储对象 #
swift
struct User: Codable {
let id: Int
let name: String
}
extension UserDefaults {
func set<T: Encodable>(_ object: T, forKey key: String) {
if let data = try? JSONEncoder().encode(object) {
set(data, forKey: key)
}
}
func get<T: Decodable>(_ type: T.Type, forKey key: String) -> T? {
if let data = data(forKey: key) {
return try? JSONDecoder().decode(T.self, from: data)
}
return nil
}
}
let user = User(id: 1, name: "张三")
UserDefaults.standard.set(user, forKey: "currentUser")
if let savedUser = UserDefaults.standard.get(User.self, forKey: "currentUser") {
print(savedUser.name)
}
2.3 实际应用 #
swift
class Settings: ObservableObject {
@Published var isDarkMode: Bool {
didSet {
UserDefaults.standard.set(isDarkMode, forKey: "isDarkMode")
}
}
@Published var fontSize: Int {
didSet {
UserDefaults.standard.set(fontSize, forKey: "fontSize")
}
}
init() {
self.isDarkMode = UserDefaults.standard.bool(forKey: "isDarkMode")
self.fontSize = UserDefaults.standard.integer(forKey: "fontSize")
}
}
三、FileManager #
3.1 文件路径 #
swift
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL = documentsURL.appendingPathComponent("data.json")
print("文档目录: \(documentsURL.path)")
print("文件路径: \(fileURL.path)")
3.2 写入文件 #
swift
let text = "Hello, World!"
do {
try text.write(to: fileURL, atomically: true, encoding: .utf8)
print("写入成功")
} catch {
print("写入失败: \(error)")
}
3.3 读取文件 #
swift
do {
let content = try String(contentsOf: fileURL, encoding: .utf8)
print(content)
} catch {
print("读取失败: \(error)")
}
3.4 删除文件 #
swift
do {
try fileManager.removeItem(at: fileURL)
print("删除成功")
} catch {
print("删除失败: \(error)")
}
3.5 存储对象 #
swift
struct User: Codable {
let id: Int
let name: String
}
func saveUser(_ user: User, to url: URL) throws {
let data = try JSONEncoder().encode(user)
try data.write(to: url)
}
func loadUser(from url: URL) throws -> User {
let data = try Data(contentsOf: url)
return try JSONDecoder().decode(User.self, from: data)
}
let user = User(id: 1, name: "张三")
let userURL = documentsURL.appendingPathComponent("user.json")
try? saveUser(user, to: userURL)
if let loadedUser = try? loadUser(from: userURL) {
print(loadedUser.name)
}
四、CoreData #
4.1 创建模型 #
swift
import CoreData
class CoreDataStack {
static let shared = CoreDataStack()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Model")
container.loadPersistentStores { _, error in
if let error = error {
fatalError("CoreData错误: \(error)")
}
}
return container
}()
var context: NSManagedObjectContext {
return persistentContainer.viewContext
}
func save() {
if context.hasChanges {
do {
try context.save()
} catch {
print("保存失败: \(error)")
}
}
}
}
4.2 创建实体 #
swift
extension UserEntity {
@nonobjc public class func fetchRequest() -> NSFetchRequest<UserEntity> {
return NSFetchRequest<UserEntity>(entityName: "UserEntity")
}
@NSManaged public var id: Int64
@NSManaged public var name: String?
@NSManaged public var email: String?
}
func createUser(id: Int, name: String, email: String) {
let context = CoreDataStack.shared.context
let user = UserEntity(context: context)
user.id = Int64(id)
user.name = name
user.email = email
CoreDataStack.shared.save()
}
4.3 查询数据 #
swift
func fetchUsers() -> [UserEntity] {
let context = CoreDataStack.shared.context
let request: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
do {
return try context.fetch(request)
} catch {
print("查询失败: \(error)")
return []
}
}
func fetchUser(byId id: Int) -> UserEntity? {
let context = CoreDataStack.shared.context
let request: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
request.predicate = NSPredicate(format: "id == %d", id)
do {
return try context.fetch(request).first
} catch {
print("查询失败: \(error)")
return nil
}
}
4.4 更新和删除 #
swift
func updateUser(_ user: UserEntity, name: String) {
user.name = name
CoreDataStack.shared.save()
}
func deleteUser(_ user: UserEntity) {
let context = CoreDataStack.shared.context
context.delete(user)
CoreDataStack.shared.save()
}
五、Keychain #
5.1 Keychain封装 #
swift
import Security
class KeychainManager {
static let shared = KeychainManager()
func save(_ value: String, forKey key: String) -> Bool {
guard let data = value.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data
]
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
func get(forKey key: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess,
let data = result as? Data,
let value = String(data: data, encoding: .utf8) else {
return nil
}
return value
}
func delete(forKey key: String) -> Bool {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key
]
let status = SecItemDelete(query as CFDictionary)
return status == errSecSuccess
}
}
5.2 使用示例 #
swift
KeychainManager.shared.save("my_api_key", forKey: "apiKey")
if let apiKey = KeychainManager.shared.get(forKey: "apiKey") {
print(apiKey)
}
KeychainManager.shared.delete(forKey: "apiKey")
六、实际应用 #
6.1 缓存管理 #
swift
class CacheManager {
static let shared = CacheManager()
private let fileManager = FileManager.default
private let cacheURL: URL
init() {
cacheURL = fileManager.urls(for: .cachesDirectory, in: .userDomainMask)[0]
}
func save<T: Encodable>(_ object: T, forKey key: String) throws {
let url = cacheURL.appendingPathComponent(key)
let data = try JSONEncoder().encode(object)
try data.write(to: url)
}
func load<T: Decodable>(_ type: T.Type, forKey key: String) throws -> T {
let url = cacheURL.appendingPathComponent(key)
let data = try Data(contentsOf: url)
return try JSONDecoder().decode(T.self, from: data)
}
func clear() throws {
let contents = try fileManager.contentsOfDirectory(at: cacheURL, includingPropertiesForKeys: nil)
for url in contents {
try fileManager.removeItem(at: url)
}
}
}
七、总结 #
本章学习了Swift数据持久化:
- UserDefaults:简单配置存储
- FileManager:文件存储
- CoreData:复杂数据管理
- Keychain:安全数据存储
最佳实践:
- 根据场景选择方案
- 敏感数据使用Keychain
- 大量数据使用CoreData
- 合理使用缓存
恭喜你完成了Swift完全指南的学习!
最后更新:2026-03-26