Last active
July 9, 2019 04:11
-
-
Save vinhnx/5a9c13bd7e037d72092ec1cbc85b6bde to your computer and use it in GitHub Desktop.
decode Swift enum and Date for Codable properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol AssetTypeConvertible { | |
// conformer just need to declare conformance to `AssetTypeConvertible` and will be auto inferred as generic `Value` | |
// and Xcode auto completion just works | |
// see AssetType below | |
associatedtype Value = Self | |
static func convertToEnum(from rawValue: String) -> Value | |
} | |
extension KeyedDecodingContainerProtocol { | |
func decodeEnumFromRawValue<T: AssetTypeConvertible>(_ rawValue: String) throws -> T { | |
guard let result = T.convertToEnum(from: rawValue) as? T else { | |
// this should never happen, since we inferred type | |
fatalError("This should never happen, since we inferred type, but here is to not force cast") | |
} | |
return result | |
} | |
} | |
struct Utilities {} | |
extension Utilities { | |
static func decodeDate<T: CodingKey>(key: T, in container: KeyedDecodingContainer<T>, using dateFormatter: DateFormatter) throws -> Date { | |
let _decoded = try container.decodeIfPresent(String.self, forKey: key) ?? "" | |
return _decoded.isEmpty ? Date() : (dateFormatter.date(from: _decoded) ?? Date()) | |
} | |
} | |
// AssetTypeConvertible usage | |
enum AssetType: String { | |
case series | |
case movie | |
case sports | |
case live | |
case unknown = "" | |
static func convert(from string: String) -> AssetType { | |
return AssetType(rawValue: string) ?? .unknown | |
} | |
} | |
// Conforms AssetType to AssetTypeConvertible protocol, so that it can be decoded in SearchItem decode | |
extension AssetType: AssetTypeConvertible { | |
static func convertToEnum(from rawValue: String) -> AssetType { | |
return .convert(from: rawValue) | |
} | |
} | |
// Codable usage | |
struct SearchItem: Codable { | |
// MARK: - Properties | |
let assetType: AssetType | |
let id: String | |
let startDate: Date | |
let endDate: Date | |
// MARK: - Value Types | |
private enum CodingKeys: String, CodingKey { | |
case assetType = "AssetType" | |
case id = "ID" | |
case startDate, endDate | |
} | |
required init(from decoder: Decoder) throws { | |
let container = try decoder.container(keyedBy: CodingKeys.self) | |
assetType = try container.decodeEnumFromRawValue(try container.decode(String.self, forKey: .assetType)) | |
id = try container.decode(String.self, forKey: .id) | |
startDate = try Utilities.decodeDate(key: .startDate, in: container, using: .searchDateFormatter) | |
endDate = try Utilities.decodeDate(key: .endDate, in: container, using: .searchDateFormatter) | |
} | |
} | |
// DateFormatter | |
extension DateFormatter { | |
static var searchDateFormatter: DateFormatter { | |
// 5/16/2019 11:55:00 AM | |
let formatter = self.posixFormatter | |
formatter.dateFormat = "MM/dd/yyyy h:mm:ss a" | |
return formatter | |
} | |
static var posixFormatter: DateFormatter { | |
// https://developer.apple.com/library/archive/qa/qa1480/_index.html | |
let formatter = DateFormatter() | |
formatter.locale = Locale(identifier: "en_US_POSIX") | |
return formatter | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment