I have a data model with UIImage, Color and TextAlignment in.
I think I have managed to conform Color and TextAlignment to Codable.
I am unsure of how to conform UIImage to Codable.
I have an attempt below which crashes when the app loads, probably because there is something wrong with line 20 because backgroundImage is initially nil.
Can anyone correct or point me in the right direction as how to fix this?
If is anything wrong with the Codable conformations below, please let me know.
Any help would be really appreciated.
Color and TextAlignment Codable below:
I think I have managed to conform Color and TextAlignment to Codable.
I am unsure of how to conform UIImage to Codable.
I have an attempt below which crashes when the app loads, probably because there is something wrong with line 20 because backgroundImage is initially nil.
Code Block Swift struct Model: Codable { private enum CodingKeys: CodingKey { case image } var backgroundColor: Color var textColor: Color var textAlignment: TextAlignment var image: UIImage? init(backgroundColor: Color = Color(.systemFill), textColor: Color = Color(.label), textAlignment: TextAlignment = .leading, image: UIImage? = nil) { self.backgroundColor = backgroundColor self.textColor = textColor self.textAlignment = textAlignment self.image = image } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let data = try container.decode(Data.self, forKey: .image) try self.init(from: decoder) self.image = UIImage(data: data) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if let image = self.image { let data = image.jpegData(compressionQuality: 1.0) try container.encode(data, forKey: .image) } } }
Can anyone correct or point me in the right direction as how to fix this?
If is anything wrong with the Codable conformations below, please let me know.
Any help would be really appreciated.
Color and TextAlignment Codable below:
Code Block Swift extension Color: Codable { private enum CodingKeys: CodingKey { case color } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self = try container.decode(Color.self, forKey: .color) try self.init(from: decoder) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(self, forKey: .color) } } extension TextAlignment: Codable { private enum CodingKeys: CodingKey { case center case leading case trailing } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if let decoded = try? container.decode(String.self, forKey: .center), decoded == "center" { self = .center } if let decoded = try? container.decode(String.self, forKey: .leading), decoded == "leading" { self = .leading } if let decoded = try? container.decode(String.self, forKey: .trailing), decoded == "trailing" { self = .trailing } try self.init(from: decoder) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case .center: try container.encode("center", forKey: .center) case .leading: try container.encode("leading", forKey: .leading) case .trailing: try container.encode("trailing", forKey: .trailing) } } }
What is critically bad in your code is that calling init(from:) from inside init(from:).Can anyone correct or point me in the right direction as how to fix this?
If is anything wrong with the Codable conformations below, please let me know.
Line 22 of Model and line 9 and line 38 of Color and TextAlignment Codable.
If you call init(from:) from inside init(from:), that causes infinite recursion and then crash.
An example of making TextAlignment conform to Codable:
Code Block extension TextAlignment: Codable { private enum TextAlignmentRawValue: Int, Codable { case leading case center case trailing init(_ textAlignment: TextAlignment) { switch textAlignment { case .leading: self = .leading case .center: self = .center case .trailing: self = .trailing } } var textAlignment: TextAlignment { switch self { case .leading: return .leading case .center: return .center case .trailing: return .trailing } } } public init(from decoder: Decoder) throws { let rawValue = try TextAlignmentRawValue(from: decoder) self = rawValue.textAlignment } public func encode(to encoder: Encoder) throws { let rawValue = TextAlignmentRawValue(self) try rawValue.encode(to: encoder) } }
The crash may be caused by infinite recursion as I said above, but your line 20 may also cause runtime issue.there is something wrong with line 20 because backgroundImage is initially nil.
You should use decodeIfPresent when you know the key may not exist in the encoded data.