|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +author: matt |
| 4 | +title: "Array backwards compatibility using Property Wrappers" |
| 5 | +date: 2020-07-07 14:19:05 +0200 |
| 6 | +comments: true |
| 7 | +categories: |
| 8 | +--- |
| 9 | + |
| 10 | +Let's assume that you're doing an application which shows your users pretty pictures of seasons. You contact your backend folks and they tell you that the world is simple, there are only three seasons: |
| 11 | + |
| 12 | +```swift |
| 13 | +enum Season: String, Decodable { |
| 14 | + case spring, summer, autumn |
| 15 | +} |
| 16 | +``` |
| 17 | +<!--more--> |
| 18 | + |
| 19 | +In order to compose things nicely, you put the seasons into a struct: |
| 20 | + |
| 21 | +```swift |
| 22 | +struct Seasons: Decodable { |
| 23 | + var available: [Season] |
| 24 | +} |
| 25 | +``` |
| 26 | + |
| 27 | +The following JSON comes from the server, it gets decoded, everything works well: |
| 28 | +```json |
| 29 | +"available": ["spring", "summer", "autumn"] |
| 30 | +// [__lldb_expr_12.Season.spring, __lldb_expr_12.Season.summer, __lldb_expr_12.Season.autumn] |
| 31 | +``` |
| 32 | + |
| 33 | +The application gets released. Time passes, winter comes and the app gets updated available seasons from the backend: |
| 34 | +```json |
| 35 | +"available": ["spring", "summer", "autumn", "winter"] |
| 36 | +``` |
| 37 | + |
| 38 | +What happens now? Your functionality breaks. |
| 39 | +Since the app can't understand `Season.winter`, no seasons get decoded. You receive a lot of bug reports, and your users are not happy ☹️ |
| 40 | + |
| 41 | +If only there was something we could do to prevent this from happening.. |
| 42 | +This seems like a nice use case for property wrappers! |
| 43 | + |
| 44 | +```swift |
| 45 | +@propertyWrapper |
| 46 | +struct IgnoreUnknown<Value: Decodable>: Decodable { |
| 47 | + var wrappedValue: [Value] |
| 48 | + |
| 49 | + private struct Empty: Decodable {} |
| 50 | + |
| 51 | + init(from decoder: Decoder) throws { |
| 52 | + var container = try decoder.unkeyedContainer() |
| 53 | + self.wrappedValue = [] |
| 54 | + while !container.isAtEnd { |
| 55 | + do { |
| 56 | + wrappedValue.append(try container.decode(Value.self)) |
| 57 | + } catch { |
| 58 | + _ = try? container.decode(Empty.self) |
| 59 | + } |
| 60 | + } |
| 61 | + } |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +This way, we simply add `@IgnoreUnknown` before our available seasons and voilà! After that, the `available` array simply skips the values it cannot understand 🚀 |
| 66 | +```swift |
| 67 | +struct Seasons: Decodable { |
| 68 | + @IgnoreUnknown |
| 69 | + var available: [Season] |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +Property Wrappers come with a lot of other great use cases. Please see [Properties](https://docs.swift.org/swift-book/LanguageGuide/Properties.html) in Apple documentation for more details 🙂 |
| 74 | + |
| 75 | +Hope this blogpost was helpful, thanks for reading! |
0 commit comments