I've read some posts on the subject on StackOverflow. As far as I understood it, I can't save every object in Swift immediately in the userdefaults. In the first step I tried to convert my dictionary to an NSData object, but already at this point, I fail. What am I doing wrong? Thanks for your help!
I want to manage app preferences in the mentioned dictionary. The dictionary with the value of a struct would be the best solution for me.
import Foundation
import UIKit
struct Properties: Codable {
var v1: String
var v2: Int
var v3: Bool
}
let userdefaults = UserDefaults.standard
var dictStruct: Dictionary<String, Properties> = [:]
dictStruct["a"] = Properties(v1: "AAA", v2: 0, v3: false)
dictStruct["b"] = Properties(v1: "BBB", v2: 1, v3: true)
let dataEncoded: Data = try NSKeyedArchiver.archivedData(withRootObject: dictStruct, requiringSecureCoding: false)
userdefaults.set(dataEncoded, forKey: "KeyData")
let dataDecoded = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(userdefaults.object(forKey: "KeyData") as! Data) as! Dictionary<String, Properties>
print(dataDecoded["a"]!.v1)
Playground execution terminated: An error was thrown and was not caught: Error Domain=NSCocoaErrorDomain Code=4866 "Caught exception during archival: -[__SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x600000fc73c0 ...
You are mixing up Codable
and NSCoding
. NSKeyed(Un)Archiver
belongs to NSCoding
. Don't use it.
The proper API for Codable
is PropertyListEncoder/-Decoder
struct Properties: Codable {
var v1: String
var v2: Int
var v3: Bool
}
let userdefaults = UserDefaults.standard
var dictStruct: Dictionary<String, Properties> = [:]
dictStruct["a"] = Properties(v1: "AAA", v2: 0, v3: false)
dictStruct["b"] = Properties(v1: "BBB", v2: 1, v3: true)
do {
let dataEncoded = try PropertyListEncoder().encode(dictStruct)
userdefaults.set(dataEncoded, forKey: "KeyData")
if let data = userdefaults.data(forKey: "KeyData") {
let dataDecoded = try PropertyListDecoder().decode([String:Properties].self, from: data)
print(dataDecoded["a"]!.v1)
}
} catch { print(error) }