Swift Codable协议…编码/解码NSCoding类

7

我有以下结构体...

struct Photo: Codable {

    let hasShadow: Bool
    let image: UIImage?

    enum CodingKeys: String, CodingKey {
        case `self`, hasShadow, image
    }

    init(hasShadow: Bool, image: UIImage?) {
        self.hasShadow = hasShadow
        self.image = image
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        hasShadow = try container.decode(Bool.self, forKey: .hasShadow)

        // This fails
        image = try container.decode(UIImage?.self, forKey: .image) 
    }

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

        // This also fails
        try container.encode(image, forKey: .image)
    }
}

编码照片失败,错误信息为...

可选项不符合可编码协议,因为UIImage不符合可编码协议

解码失败,错误信息为...

在期望非可选类型Optional的编码键“image”时未找到该键

是否有一种方法可以对包含符合NSCoding协议的NSObject子类属性(例如UIImageUIColor等)的Swift对象进行编码?


4
你需要编写自定义的编码/解码代码来将对象存档/取消存档为 Data。请查阅 编码和解码自定义类型 - vadian
1个回答

9
感谢@vadian指引我在编码/解码数据方面的方向...
class Photo: Codable {

    let hasShadow: Bool
    let image: UIImage?

    enum CodingKeys: String, CodingKey {
        case hasShadow, imageData
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        hasShadow = try container.decode(Bool.self, forKey: .hasShadow)

        if let imageData = try container.decodeIfPresent(Data.self, forKey: .imageData) {
            image = NSKeyedUnarchiver.unarchiveObject(with: imageData) as? UIImage
        } else {
            image = nil
        }
    }

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

        if let image = image {
            let imageData = NSKeyedArchiver.archivedData(withRootObject: image)
            try container.encode(imageData, forKey: .imageData)
        }
    }
}

1
所以最终使用“自定义类型”时,Codable并没有真正简化任何事情,是吗? :-| - d4Rk
它允许您对非NSObject子类(枚举和结构体)进行编码/解码。 - Ashley Mills
@AshleyMills,我在复制这段代码到我的文件时遇到了错误:“类型'Photo'不符合协议'Decodable'”。 - Gopal Devra
@GopalDevra 请将此作为另一个问题提出。 - Ashley Mills

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接