Вы можете расширить CaseIterable
, ограничив Self
до Equatable
. Тогда вам просто нужно найти индекс после firstIndex
вашего CaseItareble
перечисления и вернуть элемент в этой позиции. Если индекс равен endIndex
во всех случаях, просто верните первый элемент.
extension CaseIterable where Self: Equatable {
var allCases: AllCases { Self.allCases }
var next: Self {
let index = allCases.index(after: allCases.firstIndex(of: self)!)
guard index != allCases.endIndex else { return allCases.first! }
return allCases[index]
}
}
Другой вариант - ограничить AllCases
значением BidirectionalCollection
. Это позволит вам получить последний элемент вашего перечисления, проверить, равен ли он самому себе, и вернуть первый элемент без необходимости перебора всей вашей коллекции:
extension CaseIterable where Self: Equatable, AllCases: BidirectionalCollection {
var allCases: AllCases { Self.allCases }
var next: Self {
guard allCases.last != self else { return allCases.first! }
return allCases[allCases.index(after: allCases.firstIndex(of: self)!)]
}
}
, расширяется на CaseIterable next и предыдущие свойства:
extension CaseIterable {
typealias Index = AllCases.Index
var first: Self { allCases.first! }
var allCases: AllCases { Self.allCases }
func index(after i: Index) -> Index { allCases.index(after: i) }
}
extension CaseIterable where AllCases: BidirectionalCollection {
var last: Self { allCases.last! }
func index(before i: Index) -> Index { allCases.index(before: i) }
}
extension CaseIterable where Self: Equatable {
var index: Index { firstIndex(of: self) }
func firstIndex(of element: Self) -> Index { allCases.firstIndex(of: element)! }
}
extension CaseIterable where Self: Equatable, AllCases: BidirectionalCollection {
var previous: Self {
first == self ? last : allCases[index(before: index)]
}
var next: Self {
last == self ? first : allCases[index(after: index)]
}
}
Тестирование игровой площадки;
enum Enum: CaseIterable {
case a,b,c
}
let value: Enum = .c
let next = value.next // a
let next2 = next.next // b
let next3 = next2.next // c
let previous = value.previous // b
let previous2 = previous.previous // a
let previous3 = previous2.previous // c