Eigentlich sind die obigen Antworten wirklich großartig, aber es fehlen einige Details für das, was viele Leute in einem kontinuierlich entwickelten Client / Server-Projekt benötigen. Wir entwickeln eine App, während sich unser Backend im Laufe der Zeit kontinuierlich weiterentwickelt, was bedeutet, dass einige Enum-Fälle diese Entwicklung ändern werden. Wir brauchen also eine Enum-Decodierungsstrategie, die Arrays von Enums dekodieren kann, die unbekannte Fälle enthalten. Andernfalls schlägt das Dekodieren des Objekts, das das Array enthält, einfach fehl.
Was ich getan habe, ist ganz einfach:
enum Direction: String, Decodable {
case north, south, east, west
}
struct DirectionList {
let directions: [Direction]
}
extension DirectionList: Decodable {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var directions: [Direction] = []
while !container.isAtEnd {
// Here we just decode the string from the JSON which always works as long as the array element is a string
let rawValue = try container.decode(String.self)
guard let direction = Direction(rawValue: rawValue) else {
// Unknown enum value found - ignore, print error to console or log error to analytics service so you'll always know that there are apps out which cannot decode enum cases!
continue
}
// Add all known enum cases to the list of directions
directions.append(direction)
}
self.directions = directions
}
}
Bonus: Implementierung ausblenden> Machen Sie es zu einer Sammlung
Implementierungsdetails zu verbergen ist immer eine gute Idee. Dafür benötigen Sie nur ein bisschen mehr Code. Der Trick besteht darin, sich DirectionsList
an Collection
Ihr internes list
Array anzupassen und es privat zu machen:
struct DirectionList {
typealias ArrayType = [Direction]
private let directions: ArrayType
}
extension DirectionList: Collection {
typealias Index = ArrayType.Index
typealias Element = ArrayType.Element
// The upper and lower bounds of the collection, used in iterations
var startIndex: Index { return directions.startIndex }
var endIndex: Index { return directions.endIndex }
// Required subscript, based on a dictionary index
subscript(index: Index) -> Element {
get { return directions[index] }
}
// Method that returns the next index when iterating
func index(after i: Index) -> Index {
return directions.index(after: i)
}
}
Weitere Informationen zum Anpassen an benutzerdefinierte Sammlungen finden Sie in diesem Blogbeitrag von John Sundell: https://medium.com/@johnsundell/creating-custom-collections-in-swift-a344e25d0bb0