You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 18:15:36