如何在NSUserDefaults中存储Swift枚举值

时间:2015-01-30 23:13:31

标签: swift

我有一个这样的枚举:

enum Environment {
    case Production
    case Staging
    case Dev
}

我想在NSUserDefaults中保存一个像这样的实例:

func saveEnvironment(environment : Environment){
    NSUserDefaults.standardUserDefaults().setObject(environment, forKey: kSavedEnvironmentDefaultsKey)
}

据我所知,Swift枚举不是NSObject,这使得难以保存,但我不确定将其转换为可存储的最佳方法是什么。

7 个答案:

答案 0 :(得分:70)

使用rawValue作为枚举是使用可存储在N​​SUserDefaults中的类型的一种方法,定义枚举以使用rawValue。原始值可以是字符串,字符或任何整数或浮点数类型:

enum Environment: String {
    case Production = "Prod"
    case Staging    = "Stg"
    case Dev        = "Dev"
}

您还可以使用rawValue(可能来自NSUserDefaults)直接创建枚举实例,例如:

 let env = Environment(rawValue: "Dev")

您可以像这样从枚举对象中提取rawValue(String),然后根据需要将其存储在NSUserDefaults中:

if let myEnv = env {
    println(myEnv.rawValue)
}


func saveEnvironment(environment : Environment){
    NSUserDefaults.standardUserDefaults().setObject(environment.rawValue, forKey: kSavedEnvironmentDefaultsKey)
}

答案 1 :(得分:15)

如果您想保存/读取UserDefaults中的数据并分离一些逻辑,您可以按照以下方式进行操作(Swift 3):

enum Environment: String {
    case Production
    case Staging
    case Dev
}

class UserDefaultsManager {

    static let shared = UserDefaultsManager()

    var environment: Environment? {
       get {
           guard let environment = UserDefaults.standard.value(forKey: kSavedEnvironmentDefaultsKey) as? String else {
               return nil
           }
           return Environment(rawValue: environment)
       }
       set(environment) {
           UserDefaults.standard.set(environment?.rawValue, forKey: kSavedEnvironmentDefaultsKey)
       }
    }
}

因此,在UserDefaults中保存数据将是这样的:

UserDefaultsManager.shared.environment = Environment.Production

读取数据,以这种方式保存在UserDefaults中:

if let environment = UserDefaultsManager.shared.environment {
    //you can do some magic with this variable
} else {
    print("environment data not saved in UserDefaults")
}

答案 2 :(得分:3)

使用<p id="time"> </p>协议

符合<Text style={styles.text}>{this.state.time.toTimeString().substring(0, 5)}</Text> 协议的范围Codable枚举,将值编码和解码为Environment

Codable

Data的包装器:

enum Environment: String, Codable {
    case Production
    case Staging
    case Dev
}

用法

UserDefaults

答案 3 :(得分:0)

我正在使用这种类型的舞台。你可以试试这个会对你有帮助。

enum Environment: String {
  case Production  = "Production URL"
  case Testing     = "Testing URl"
  case Development = "Development URL"
}
//your button actions
 // MARK: set Development api
  @IBAction func didTapDevelopmentAction(_ sender: Any) {
    let env = Environment.Development.rawValue
    print(env)
    UserDefaults.standard.set(env, forKey:Key.UserDefaults.stagingURL)
  }
// MARK: set Production api
  @IBAction func didTapProductionAction(_ sender: Any) {
    let env = Environment.Production.rawValue
    print(env)
    UserDefaults.standard.set(env, forKey:Key.UserDefaults.stagingURL)
  }

  // MARK: set Testing api
  @IBAction func didTapTestingAction(_ sender: Any) {
    let env = Environment.Testing.rawValue
    print(env)
    UserDefaults.standard.set(env, forKey:Key.UserDefaults.stagingURL)
  }
//Based on selection act
print("\(UserDefaults.standard.object(forKey: "stagingURL") ?? "")")

答案 4 :(得分:0)

Swift 5.1 您可以为此创建属性包装器

@propertyWrapper final class UserDefaultsLanguageValue {
    var defaultValue: LanguageType
    var key: UserDefaultsKey

    init(key: UserDefaultsKey, defaultValue: LanguageType) {
        self.key = key
        self.defaultValue = defaultValue
    }

    var wrappedValue: LanguageType {
        get { LanguageType(rawValue: UserDefaults.standard.object(forKey: key.rawValue) as? String ?? defaultValue.rawValue) ?? .en }
        set { UserDefaults.standard.set(newValue.rawValue, forKey: key.rawValue) }
    }
}

enum UserDefaultsKey: String {
    case language
}

enum LanguageType: String {
    case en
    case ar
}

并像这样使用它

@UserDefaultsLanguageValue(key: .language, defaultValue: LanguageType.en) var language

答案 5 :(得分:0)

这是另一种可供选择的方法,可以轻松地与基于NSUserDefaults可以存储的类型(如String,Int等)的枚举一起使用。

@propertyWrapper
struct StoredProperty<T: RawRepresentable> {
    let key: String
    let defaultValue: T

    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    var wrappedValue: T {
        get {
            guard let rawValue = UserDefaults.standard.object(forKey: key) as? T.RawValue, let value = T(rawValue: rawValue) else {
                 return defaultValue
            }
            return value
        }
        set {
            UserDefaults.standard.set(newValue.rawValue, forKey: key)
        }
    }
}

用法示例:

enum Environment: String {
    case Production
    case Staging
    case Dev
}

@StoredProperty("Environment", defaultValue: .Dev)
var storedProperty: Environment

答案 6 :(得分:0)

Swift 5.1您可以使用Codable创建值来传入和传出UserDefaults来创建通用属性包装器

extension UserDefaults {
    // let value: Value already set somewhere
    // UserDefaults.standard.set(newValue, forKey: "foo")
    //
    func set<T>(_ 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<T>(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<Value>: 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

}