将自定义对象转换为要保存在NSUserDefauts中的数据

问题描述

我们有一个自定义对象设置,如下所示:

struct BallPark: Codable,Equatable  {
    static func == (lhs: LeanVenue,rhs: LeanVenue) -> Bool {
        return lhs.id == rhs.id
    }
    let id: String
    let name: String?
    let location: VenueCoordinates?
    let mapEnabled: Bool?
    let facilityStatus: String?
    }

struct VenueCoordinates: Codable {
    let latitude: String?
    let longitude: String?
    
    var lat: Double? {
        guard let latitud = latitude else { return nil}
        return Double(latitud)
    }
    var lon: Double? {
        guard let longitude = longitude else { return nil}
        return Double(longitude)
    }
}

我们正在尝试将其转换为数据类型,以便可以将其保存为用户默认值,如下所示:

guard let bestBallParkToSave = theBestBallPark // this is of type BallPark,after fetching data

其他{return}

 let encodedBestBallPark = NSKeyedArchiver.archivedData(withRootObject: bestBallParkToSave)
            
 UserDefaults.standard.set(encodedBestBallPark,forKey: "favoriteBallPark")

问题是尝试转换时会导致错误:

“ NSInvalidArgumentException”,原因:“-[__ SwiftValue encodeWithCoder:]:无法识别的选择器已发送到实例 0x6000027dca80'

我尝试使用以下堆栈溢出答案:How to convert custom object to Data Swift,但是除了确保它符合Codable(我相信我的结构及其中的所有内容都符合)之外,实际上并没有一个明确的答案。如果您有任何建议,请告诉我。

解决方法

那里的问题。是您将Codable与NSCoding混为一谈。要使用NSKeyedArchiver的archivedData方法,您需要具有一个符合NSCoding的类。在这种情况下,您具有符合Codable的结构,因此您需要使用JSONEncoder编码方法。注意:您的等价方法声明是错误的:

struct BallPark: Codable,Equatable  {
    static func == (lhs: Self,rhs: Self) -> Bool {
        return lhs.id == rhs.id
    }
    let id: String
    let name: String?
    let location: VenueCoordinates?
    let mapEnabled: Bool?
    let facilityStatus: String?
}

struct VenueCoordinates: Codable {
    let latitude: String?
    let longitude: String?
    
    var lat: Double? {
        guard let latitud = latitude else { return nil}
        return Double(latitud)
    }
    var lon: Double? {
        guard let longitude = longitude else { return nil}
        return Double(longitude)
    }
}

let bestBallParkToSave = BallPark.init(id: "1",name: "Steve",location: .init(latitude: "20.0",longitude: "40.0"),mapEnabled: true,facilityStatus: "a status")

do {
    let encodedBestBallPark = try JSONEncoder().encode(bestBallParkToSave)
    UserDefaults.standard.set(encodedBestBallPark,forKey: "favoriteBallPark")
    if let ballParkData = UserDefaults.standard.data(forKey: "favoriteBallPark") {
        let loadedBallPark = try JSONDecoder().decode(BallPark.self,from: ballParkData)
        print(loadedBallPark)  // BallPark(id: "1",name: Optional("Steve"),location: Optional(VenueCoordinates(latitude: Optional("20.0"),longitude: Optional("40.0"))),mapEnabled: Optional(true),facilityStatus: Optional("a status"))
    }
} catch {
     print(error)
}

您还可以通过扩展UserDefaults并创建海关编码和解码方法来简化生活:

extension UserDefaults {
    func decode<T: Decodable>(_ type: T.Type,forKey defaultName: String) throws -> T {
        try JSONDecoder().decode(T.self,from: data(forKey: defaultName) ?? .init())
    }
    func encode<T: Encodable>(_ value: T,forKey defaultName: String) throws {
        try set(JSONEncoder().encode(value),forKey: defaultName)
    }
}

用法:

let bestBallParkToSave = BallPark(id: "1",facilityStatus: "a status")
do {

    try UserDefaults.standard.encode(bestBallParkToSave,forKey: "favoriteBallPark")
    let loadedBallPark = try UserDefaults.standard.decode(BallPark.self,forKey: "favoriteBallPark")
    print(loadedBallPark)  // BallPark(id: "1",facilityStatus: Optional("a status"))
    
} catch {
     print(error)
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...