How can I store a Swift enum value in NSUserDefaults

前端 未结 7 736
猫巷女王i
猫巷女王i 2021-01-31 07:47

I have an enum like this:

enum Environment {
    case Production
    case Staging
    case Dev
}

And I\'d like to save an instance in NSUserDef

7条回答
  •  孤城傲影
    2021-01-31 07:55

    Swift 5.1 You can create a generic property wrapper, using Codable to transform values in and out the UserDefaults

    extension UserDefaults {
        // let value: Value already set somewhere
        // UserDefaults.standard.set(newValue, forKey: "foo")
        //
        func set(_ value: T, forKey: String) where T: Encodable {
            if let encoded = try? JSONEncoder().encode(value) {
                setValue(encoded, forKey: forKey)
            }
        }
    
        // let value: Value? = UserDefaults.standard.get(forKey: "foo")
        //
        func get(forKey: String) -> T? where T: Decodable {
            guard let data = value(forKey: forKey) as? Data,
                let decodedData = try? JSONDecoder().decode(T.self, from: data)
                else { return nil }
            return decodedData
        }
    }
    
    @propertyWrapper
    public struct UserDefaultsBacked: Equatable where Value: Equatable, Value: Codable {
        let key: String
        let defaultValue: Value
        var storage: UserDefaults = .standard
    
        public init(key: String, defaultValue: Value) {
            self.key = key
            self.defaultValue = defaultValue
        }
    
        // if the value is nil return defaultValue
        // if the value empty return defaultValue
        // otherwise return the value
        //
        public var wrappedValue: Value {
            get {
                let value: Value? = storage.get(forKey: key)
                if let stringValue = value as? String, stringValue.isEmpty {
                    // for string values we want to equate nil with empty string as well
                    return defaultValue
                }
                return value ?? defaultValue
            }
            set {
                storage.set(newValue, forKey: key)
                storage.synchronize()
            }
        }
    }
    
    // use it
    struct AppState: Equatable {
        enum TabItem: String, Codable {
            case home
            case book
            case trips
            case account
        }
        var isAppReady = false
    
        @UserDefaultsBacked(key: "selectedTab", defaultValue: TabItem.home)
        var selectedTab
        // default value will be TabItem.home
    
        @UserDefaultsBacked(key: "selectedIndex", defaultValue: 33)
        var selectedIndex
        // default value will be 33
    
    }
    
    

提交回复
热议问题