protocol CircularEnum: CaseIterable where Self.AllCases.Element: Equatable { var currentIndex: Self.AllCases.Index { get } func next() -> Self.AllCases.Element func previous() -> Self.AllCases.Element } extension CircularEnum { var currentIndex: Self.AllCases.Index { return Self.allCases.firstIndex(of: self)! } func next() -> Self.AllCases.Element { let allCases = Self.allCases let nextIndex = allCases.index(after: currentIndex) if nextIndex == allCases.endIndex { return allCases.first! } return allCases[nextIndex] } func previous() -> Self.AllCases.Element { let allCases = Self.allCases var index = currentIndex if index == allCases.startIndex { index = allCases.endIndex } index = allCases.index(index, offsetBy: -1) return allCases[index] } } enum Season: CircularEnum { case winter case spring case summer case fall } let season = Season.fall season.previous() // summer season.next() // winter