如何在NSUserDefaults中存储Swift枚举值

rob*_*rob 43 swift

我有这样的枚举:

enum Environment {
    case Production
    case Staging
    case Dev
}
Run Code Online (Sandbox Code Playgroud)

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

func saveEnvironment(environment : Environment){
    NSUserDefaults.standardUserDefaults().setObject(environment, forKey: kSavedEnvironmentDefaultsKey)
}
Run Code Online (Sandbox Code Playgroud)

我知道Swift枚举不是NSObject,这使得它很难保存,但我不确定将它转换为可存储的东西的最佳方法是什么.

use*_*374 74

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

enum Environment: String {
    case Production = "Prod"
    case Staging    = "Stg"
    case Dev        = "Dev"
}
Run Code Online (Sandbox Code Playgroud)

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

let env = Environment(rawValue: "Dev")
Run Code Online (Sandbox Code Playgroud)

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

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


func saveEnvironment(environment : Environment){
    NSUserDefaults.standardUserDefaults().setObject(environment.rawValue, forKey: kSavedEnvironmentDefaultsKey)
}
Run Code Online (Sandbox Code Playgroud)

  • 对于那些寻找阅读... myEnv = Environment(rawValue:defaults.stringForKey(kSavedEnvironmentDefaultsKey))! (12认同)
  • 对于在枚举上的 `rawValue` 初始值设定项或属性有问题的任何人,请确保您的枚举扩展了 `rawValue` 的类型。例如,在 OP 的示例中,`Environment` 扩展了 `String`。我第一次错过了这个。 (2认同)
  • 如果你扩展的类型是`String`或`Int`的文字可转换,你甚至不需要为每种情况定义显式原始值,因为它们可以与你扩展的类型一致地自动分配:包含一个字符串`String`枚举的案例名称; "Int","Float"和"Double"枚举的渐进数字. (2认同)

mkk*_*lik 18

如果您想保存/读取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)
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

UserDefaultsManager.shared.environment = Environment.Production
Run Code Online (Sandbox Code Playgroud)

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

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


Öme*_*ürk 5

使用Codable协议

Environment符合Codable协议的范围枚举将值编码和解码为Data.

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

Run Code Online (Sandbox Code Playgroud)

包装器UserDefaults

struct UserDefaultsManager {
    static var userDefaults: UserDefaults = .standard
    
    static func set<T>(_ value: T, forKey: String) where T: Encodable {
        if let encoded = try? JSONEncoder().encode(value) {
            userDefaults.set(encoded, forKey: forKey)
        }
    }
    
    static func get<T>(forKey: String) -> T? where T: Decodable {
        guard let data = userDefaults.value(forKey: forKey) as? Data,
            let decodedData = try? JSONDecoder().decode(T.self, from: data)
            else { return nil }
        return decodedData
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

// Set
let environment: Environment = .Production
UserDefaultsManager.set(environment, forKey: "environment")

// Get
let environment: Environment? = UserDefaultsManager.get(forKey: "environment")

Run Code Online (Sandbox Code Playgroud)

  • 当然。它们是原始类型并且已经符合“Codable”。去尝试一下。 (2认同)