Swift中为枚举关联对应类型,实现强类型LocalStorage协议
实现强类型约束的LocalStorage(基于依赖倒置原则)
要解决你的问题,核心是让每个存储Key与对应的值类型在编译期绑定,避免Any类型带来的类型不安全问题,同时保留依赖倒置的抽象性。以下是具体实现方案:
1. 定义带类型关联的Key协议
首先创建一个协议,用来关联存储Key和对应的值类型,同时要求值类型遵循Codable(若仅存储基础类型可移除该约束):
protocol TypedStorageKey { associatedtype Value: Codable var rawKey: String { get } }
2. 绑定Key与对应类型
用枚举+静态属性的方式封装Key,兼顾枚举的便捷性和强类型约束:
// 示例存储类型 struct User: Codable { let name: String let id: Int } struct Account: Codable { let accountName: String let balance: Double } // 保留枚举式访问 enum LocalStorageKeys { static let user = UserKey() static let account = AccountKey() } // 每个Key对应单独结构体,绑定具体类型 private struct UserKey: TypedStorageKey { typealias Value = User let rawKey = "user" } private struct AccountKey: TypedStorageKey { typealias Value = Account let rawKey = "account" }
3. 重构LocalStorage协议
修改协议方法,利用泛型关联Key的类型,实现编译期类型检查:
protocol LocalStorage { func save<Key: TypedStorageKey>(key: Key, value: Key.Value) throws func get<Key: TypedStorageKey>(key: Key) -> Key.Value? }
4. 实现UserDefaults扩展
让UserDefaults遵循LocalStorage协议,完成具体存储逻辑:
extension UserDefaults: LocalStorage { func save<Key: TypedStorageKey>(key: Key, value: Key.Value) throws { let data = try JSONEncoder().encode(value) set(data, forKey: key.rawKey) } func get<Key: TypedStorageKey>(key: Key) -> Key.Value? { guard let data = data(forKey: key.rawKey) else { return nil } return try? JSONDecoder().decode(Key.Value.self, from: data) } }
5. 使用示例
调用时会自动进行类型约束,错误类型会在编译期直接报错:
// 抽象依赖,符合依赖倒置原则 let localStorage: LocalStorage = UserDefaults.standard let testUser = User(name: "Alice", id: 1001) let testAccount = Account(accountName: "alice_bank", balance: 5000.0) // 正确用法:仅能传入User类型给.user Key try localStorage.save(key: LocalStorageKeys.user, value: testUser) // 错误用法:传入Account类型给.user Key会编译报错 // try localStorage.save(key: LocalStorageKeys.user, value: testAccount) // 自动推断返回值为User? let savedUser = localStorage.get(key: LocalStorageKeys.user) // 自动推断返回值为Account? let savedAccount = localStorage.get(key: LocalStorageKeys.account)
核心优势
- 强类型约束:编译期拦截错误类型传入,彻底避免非法赋值
- 依赖倒置:LocalStorage协议不依赖具体存储实现,可轻松替换为自定义缓存等方案
- 自动类型推断:get方法无需手动指定类型,编译器根据Key自动推导返回值类型
内容的提问来源于stack exchange,提问作者Daniel Ramos
相关产品推荐
相关产品推荐

