首页 > 解决方案 > JSON,可编码,图像,试图通过将图像转换为base64来编码包含图像的结构数组

问题描述

我有一个带有图像的结构数组。我需要将其保存到文件中以保持持久性。我可以将其转换为 Image 或 base64。

struct p: Identifiable, Hashable {
  var image: UIImage? = nil
  var name: String = ""
}

struct pD: Codable {
  var image: String = ""   //base64
  var name: String = ""
}

var pA = [p]
var pDA = [pD]

func convertImage2base64()

将 p 转换为 pD 的最便宜的方法是什么?我有带有图像和名称的 JSON 文件,我通过从 base64 图像和名称的 JSON 手动构建结构数组来导入该文件。

到达 pD 的重点是让我可以立即进行 JSONdecode,而不是重建一个全新的临时结构数组。我觉得使用 map 进行数组转换可能会使其工作,但我就是想不通。

我目前正在循环中使用 convertImage2base64() 复制数组的单个元素。这似乎是一个太昂贵的过程。

数据集不值得核心数据设置。

标签: iosjsonswiftimagejsondecoder

解决方案


将图像存储为 Base64 在存储空间、内存和计算方面非常昂贵。我不推荐它,除非有特殊需要。如果你想要一个静态 JSON 文件,那么我建议将图像存储在单独的文件中(如 PNG 或 JPG 或其他任何文件),并在必要时将它们的 URL 存储在 JSON 中。如果您要存储的只是名称和图像,那么我会将它们放在一个目录中,并让名称成为文件名。那么文件系统就是你的数据库。在这种情况下不需要 JSON。如果需要,也可以将少量元数据放入文件名中。

如果要将所有内容存储在单个文件中,请查看二进制属性列表。它们可以直接存储Data,无需浪费地转换为Base64,并直接支持Codeable。


如果这也是您的服务器协议,而不仅仅是您描述的持久性模型,并且您更喜欢将其作为 Base64 编码的 JSON 进行管理,而不是更有效的二进制协议,那么 Codable 可以直接处理它。

extension P: Codable {
    enum CodingKeys: String, CodingKey {
        case image, name
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(name, forKey: .name)
        try container.encodeIfPresent(image?.pngData()?.base64EncodedString(), forKey: .image)
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        let imageB64 = try container.decode(String.self, forKey: .image)
        if let imageData = Data(base64Encoded: imageB64) {
            self.image = UIImage(data: imageData)
        }
    }
}

以这种方式在本地对持久存储进行编码效率非常低,但正如您所说,iPhone 可以处理计算。但是,如果有很多小的更改(这会降低用户的闪存存储,它具有有限的写入次数),就会有很多磁盘流失,但它应该可以工作。


推荐阅读