How to get next case of enum(i.e. write a circulating method) in Swift 4.2

前端 未结 2 913
感情败类
感情败类 2021-01-11 14:59

Swift 4.2 introduces a new CaseIterable protocol that automatically generates an array property of all cases in an enum.
Now I want to implement a default m

2条回答
  •  生来不讨喜
    2021-01-11 15:06

    Some problems with your approach are:

    • The Collection protocol does not define a last property.
    • In order to compare the elements with == they have to be Equatable.
    • Collection indices are not necessarily integers, they must be incremented with index(after:).

    This seems to be a working solution (tested with Xcode 10.0 beta 2):

    extension CaseIterable where Self: Equatable {
        func next() -> Self {
            let all = Self.allCases
            let idx = all.index(of: self)!
            let next = all.index(after: idx)
            return all[next == all.endIndex ? all.startIndex : next]
        }
    }
    

    Example:

    enum Direction: CaseIterable {
        case east, south, west, north
    }
    
    print(Direction.east.next()) // south
    print(Direction.north.next()) // east
    

    Remarks:

    • Only enumerations without associated values are CaseIterable, and those are also Equatable (but the compiler does not figure out that by itself). Therefore Self: Equatable is not a real restriction.
    • Self.allCases can be used in Swift 4.2 to access the type property from an instance method.
    • The forced unwrapping is safe because we know that the value is an element of allCases.
    • Your enum Direction: CaseIterable compiles because the concrete enum Direction type is Equatable, and its Direction.allCases is an Array – which has integer indices and a last property.

提交回复
热议问题