如何使UIImage与Codable兼容? [英] How to conform UIImage to Codable?

查看:272
本文介绍了如何使UIImage与Codable兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Swift 4具有可编码,它很棒。但是 UIImage 默认情况下不符合该要求。我们该怎么做?

Swift 4 has Codable and it's awesome. But UIImage does not conform to it by default. How can we do that?

我尝试过 singleValueContainer unkeyedContainer

extension UIImage: Codable {
  // 'required' initializer must be declared directly in class 'UIImage' (not in an extension)
  public required init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    let data = try container.decode(Data.self)
    guard let image = UIImage(data: data) else {
      throw MyError.decodingFailed
    }

    // A non-failable initializer cannot delegate to failable initializer 'init(data:)' written with 'init?'
    self.init(data: data)
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()
    guard let data = UIImagePNGRepresentation(self) else {
      return
    }

    try container.encode(data)
  }
}

我遇到2个错误


  1. 'required'初始值设定项必须在类'UIImage'中直接声明(不在扩展名中)

  2. 不可失败的初始化程序无法委派给使用 init?编写的可失败的初始化程序 init(data :)。

一种解决方法是使用包装器。但是还有其他方法吗?

A workaround is to use wrapper. But are there any other ways?

推荐答案

一种解决方案:滚动自己的符合Codable的包装类。



一种解决方案是将图像包装在您拥有的新类中,因为扩展了 UIImage 。否则,您的尝试基本上是直接的。我在Hyper Interactive称为[a href = https://github.com/hyperoslo/Cache#what-about-images rel = noreferrer>缓存的缓存框架中看到了漂亮的效果。

A solution: roll your own wrapper class conforming to Codable.

One solution, since extensions to UIImage are out, is to wrap the image in a new class you own. Otherwise, your attempt is basically straight on. I saw this done beautifully in a caching framework by Hyper Interactive called, well, Cache.

尽管您需要访问库以深入研究依赖项,但可以通过查看它们的 ImageWrapper code>类,其构建方式如下:

Though you'll need to visit the library to drill down into the dependencies, you can get the idea from looking at their ImageWrapper class, which is built to be used like so:

let wrapper = ImageWrapper(image: starIconImage)
try? theCache.setObject(wrapper, forKey: "star")

let iconWrapper = try? theCache.object(ofType: ImageWrapper.self, forKey: "star")
let icon = iconWrapper.image



这是他们的包装器类:



Here is their wrapper class:

// Swift 4.0
public struct ImageWrapper: Codable {
  public let image: Image

  public enum CodingKeys: String, CodingKey {
    case image
  }

  // Image is a standard UI/NSImage conditional typealias
  public init(image: Image) {
    self.image = image
  }

  public init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let data = try container.decode(Data.self, forKey: CodingKeys.image)
    guard let image = Image(data: data) else {
      throw StorageError.decodingFailed
    }

    self.image = image
  }

  // cache_toData() wraps UIImagePNG/JPEGRepresentation around some conditional logic with some whipped cream and sprinkles.
  public func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    guard let data = image.cache_toData() else {
        throw StorageError.encodingFailed
    }

    try container.encode(data, forKey: CodingKeys.image)
  }
}

我很想听听您最终使用的内容。

I'd love to hear what you end up using.

更新:事实证明, OP编写了我所引用的代码(对Cache的Swift 4.0更新)来解决该问题。当然,代码应该放在这里,但由于所有这些都具有戏剧性的讽刺意味,因此我也不会编辑我的文字。 :)

UPDATE: It turns out the OP wrote the code that I referenced (the Swift 4.0 update to Cache) to solve the problem. The code deserves to be up here, of course, but I'll also leave my words unedited for the dramatic irony of it all. :)

这篇关于如何使UIImage与Codable兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆