Swift 4 has Codable and it's awesome. But UIImage does not conform to it by default. How can we do that?
I tried with singleValueContainer and 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)
}
}
I get 2 errors
- 'required' initializer must be declared directly in class 'UIImage' (not in an extension)
- A non-failable initializer cannot delegate to failable initializer 'init(data:)' written with 'init?'
A workaround is to use wrapper. But are there any other ways?
A solution: roll your own wrapper class conforming to Codable.
One solution, since extensions to
UIImageare 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.Though you'll need to visit the library to drill down into the dependencies, you can get the idea from looking at their
ImageWrapperclass, which is built to be used like so:Here is their wrapper class:
I'd love to hear what you end up using.
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. :)