Value not found when retrieving from UserDefaults

爱⌒轻易说出口 提交于 2020-08-10 18:52:47

问题


This is the exact error I get:

valueNotFound(Foundation.Data, Swift.DecodingError.Context(codingPath: [_PlistKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "wishData", intValue: nil), _PlistKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "image", intValue: nil)], debugDescription: "Expected Data value but found null instead.", underlyingError: nil))

Details:

I have two custom strcuts :

Wishlist :

struct Wishlist: Codable {
var name: String
var image: UIImage
var wishes: [Wish]
var color: UIColor
var textColor: UIColor
var index: Int

enum CodingKeys: String, CodingKey {
    case name, image, wishData, color, textColor, index
}

init(name: String, image: UIImage, wishes: [Wish], color: UIColor, textColor: UIColor, index: Int) {
    self.name = name
    self.image = image
    self.wishes = wishes
    self.color = color
    self.textColor = textColor
    self.index = index
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)

    name = try values.decode(String.self, forKey: .name)
    wishes = try values.decode([Wish].self, forKey: .wishData)
    color = try values.decode(Color.self, forKey: .color).uiColor
    textColor = try values.decode(Color.self, forKey: .textColor).uiColor
    index = try values.decode(Int.self, forKey: .index)

    let data = try values.decode(Data.self, forKey: .image)
    guard let image = UIImage(data: data) else {
        throw DecodingError.dataCorruptedError(forKey: .image, in: values, debugDescription: "Invalid image data")
    }
    self.image = image
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)

    try container.encode(name, forKey: .name)
    try container.encode(wishes, forKey: .wishData)
    try container.encode(Color(uiColor: color), forKey: .color)
    try container.encode(Color(uiColor: textColor), forKey: .textColor)
    try container.encode(index, forKey: .index)
    try container.encode(image.pngData(), forKey: .image)
}
}

And Wish

struct Wish: Codable {
public var name: String
public var checkedStatus: Bool
public var link: String
public var price: String
public var note: String
public var image: UIImage

init(name: String, link: String, price: String, note: String, image: UIImage, checkedStatus: Bool) {
    self.name = name
    self.checkedStatus = checkedStatus
    self.link = link
    self.price = price
    self.note = note
    self.image = image
}

enum CodingKeys: String, CodingKey {
    case name, checkedStatus, link, price, note, image
}

init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)

    name = try values.decode(String.self, forKey: .name)
    checkedStatus = try values.decode(Bool.self, forKey: .checkedStatus)
    link = try values.decode(String.self, forKey: .link)
    price = try values.decode(String.self, forKey: .price)
    note = try values.decode(String.self, forKey: .note)

    let data = try values.decode(Data.self, forKey: .image)
    guard let image = UIImage(data: data) else {
        throw DecodingError.dataCorruptedError(forKey: .image, in: values, debugDescription: "Invalid image data")
    }
    self.image = image
}

func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)

    try container.encode(name, forKey: .name)
    try container.encode(checkedStatus, forKey: .checkedStatus)
    try container.encode(link, forKey: .link)
    try container.encode(price, forKey: .price)
    try container.encode(note, forKey: .note)
    try container.encode(image.pngData(), forKey: .image)
}
}

Setting to UserDefaults works without any error but getting fires the error above:

func getDataSourceArray() -> [Wishlist]? {
    if let data = self.value(forKey: Keys.dataSourceKey) as? Data {
        do {
            _ = try PropertyListDecoder().decode(Array < Wishlist > .self, from: data) as [Wishlist]
        } catch let error {
            print(error)
        }
        if let dataSourceArray =
            try? PropertyListDecoder().decode(Array < Wishlist > .self, from: data) as[Wishlist] {
                return dataSourceArray
            } 
    }
    return nil
}

I know this might be quite confusing so let me know if there is anything you need to know. Im stuck here and have no idea what the problem is..


回答1:


Image data is nil

"image", intValue: nil)], debugDescription: "Expected Data value but found null instead."

so alter code in init(from decoder: Decoder) throws {

if let data = try? values.decodeIfPresent(Data.self, forKey: .image),let image = UIImage(data: data) {
     self.image = image
}

With

public var image: UIImage?

and in your custom init do

, image: UIImage? = nil

Also change

try container.encode(image.pngData(), forKey: .image)

to

if let img = image , let im = img.pngData() {
  try container.encode(im, forKey: .image)
}


来源:https://stackoverflow.com/questions/62941032/value-not-found-when-retrieving-from-userdefaults

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!