I’m looking to save a swift struct that includes a dictionary to data using NSKeyedArchiver. The reason I’m using NSKeyedArchiver is because the dictionary has a non-codable variable associated with it. I'm following this guide from Paul Hudson.
The problem I’m running into is that I keep getting the error "The data couldn’t be written because it isn’t in the correct format." at " let encoded = try encoder.encode(test) " This seems to work with non-codable types, but not when they are in a dictovnay. Does anyone know of a way to get this working? Here is the code:
import SwiftUI
import Combine
import HealthKit
struct Testing: View {
func saveData(){
let test = TestHealthSample(
myHKUnit : [Unit.imperial : HKUnit.kilocalorie(), Unit.metric : HKUnit.kilocalorie()],
isFavorite: true
)
let encoder = JSONEncoder()
do {
let encoded = try encoder.encode(test)
let str = String(decoding: encoded, as: UTF8.self)
print(str)
} catch {
print(error.localizedDescription)
}
}
var body: some View {
Text("Test")
.onAppear{
self.saveData()
}
}
}
struct TestHealthSample{
var myHKUnit : [Unit: HKUnit]
var isFavorite : Bool
}
extension TestHealthSample: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TestCodingKeys.self)
isFavorite = try container.decode(Bool.self, forKey: .isFavorite)
let hkUnitData = try container.decode(Data.self, forKey: .myHKUnit)
myHKUnit = try (NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(hkUnitData) as? [Unit:HKUnit]) ?? [Unit.metric : HKUnit.count()]
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: TestCodingKeys.self)
try container.encode(isFavorite, forKey: .isFavorite)
let hkUnitData = try NSKeyedArchiver.archivedData(withRootObject: myHKUnit, requiringSecureCoding: false)
try container.encode(hkUnitData, forKey: .myHKUnit)
}
}
enum TestCodingKeys: String, CodingKey {
case myHKUnit
case isFavorite
}
enum Unit : String, Codable{
case metric
case imperial
}
print(error.localizedDescription)
toprint(error)
to get more detail. – rmaddyCodable
andNSCoding
. The latter doesn't work at all with structs. DropNSKeyedArchiver
and use onlyCodable
– vadianCodable
if possible or write a wrapper. – vadian