Skip to content

Releases: RougeWare/Swift-SerializationTools

1.1 • `CodableBridge`

28 Dec 01:54
4d151e1
Compare
Choose a tag to compare

This adds CodableBridge, which bridges the gap between NSCoding and Codable!

Codable is the Swift re-imagining of NSCoding. I think we all can agree that Codable is much better!

But, some things (especially in Apple frameworks) conform to NSCoding but not Codable! What is one to do?

Well, never fear! A solution* is here!

// Probably the most common way that I run into this is with AppKit and UIKit, so let's use those as examples!

struct User: Codable, Equatable {
    let name: String
    let avatar: UIImage.CodableBridge?
    let favoriteColor: UIColor.CodableBridge
}


// I'll only use one instance this time, because I think it's enough to get the point across.
// Here's Redd. He likes the color red!
//
// Here we see the concession to the API user: they have to use `.codable` to create the codable bridge.
// I recommend making a sugary initializer which just takes the base type, like
// `init(name: String, avatar: UIImage, favoriteColor: UIColor)`

let redd = User(
    name: "Redd",
    avatar: UIImage(named: "Redd-avatar").codable,
    favoriteColor: UIColor(hue: 0.111, saturation: 0.78, brightness:  0.96, alpha: 1).codable
)


// And I'm sure you expect this, but that struct needs nothing more special to be able to encode &and decode it!

let reddJsonString = try redd.jsonString()
// Essentially {"name":"Redd","avatar":"<insert Base64 nonsense here>","favoriteColor":"<insert Base64 nonsense here>"}


let decodedRedd = try User(jsonString: reddJsonString)


// And of course the decoded value is just the same as before it was encoded, just like any native `Codable` type:

assert(decodedRedd == redd)


// The other caveat is that accessing the base type's methods is a bit indirect as well:

redd.favoriteColor.value.set()


// But at least accessing fields is straightforawrd thanks to `@dynamicMemberLookup`:

print(redd.avatar.size)

* Due to the limitations of Swift's approach to reference type initializers, a true Codable implementation can't be synthesized on all NSCoding types without risking a crash for invalid data. As such, I've decided to make a synthesized subtype of all NSCoding types, which can be as easily (en/de)coded. I tried to make this as ergonomic as possible; let me know if you have any better ideas!

Patch changes

1.1.1

  • Added automatic conformance to Equatable andor Hashable if its base type conforms to them

1.0.0 - MVP

18 Dec 05:28
4eb7d5e
Compare
Choose a tag to compare

Kicking this off with a pattern I've used in bunches of projects in my past. This vastly simplifies (de)serializing to/from JSON.

This applies to all Codable types! Just import SerializationTools and you get this for free:

import SerializationTools

let deserialized = try MyStruct(jsonData: someData)

let serialized = try deserialized.jsonString()