enum Suit: String { case spades = "♠" case hearts = "♥" case diamonds = "♦" case clubs = "♣" }
例如,我该如何做:
for suit in Suit { // do something with suit print(suit.rawValue) }
结果示例:
♠ ♥ ♦ ♣
我做了一个实用函数iterateEnum()用于迭代任意枚举类型的情况。
这里是使用示例:
enum Suit:String { case Spades = "♠" case Hearts = "♥" case Diamonds = "♦" case Clubs = "♣" } for f in iterateEnum(Suit) { println(f.rawValue) }
输出:
♠ ♥ ♦ ♣
但是,这只是为了调试或测试目的:这依赖于几个未记录的电流(Swift1.1)编译器行为。所以,使用它在你自己的风险:)
这里是代码:
func iterateEnum<T: Hashable>(_: T.Type) -> GeneratorOf<T> { var cast: (Int -> T)! switch sizeof(T) { case 0: return GeneratorOf(GeneratorOfOne(unsafeBitCast((),T.self))) case 1: cast = { unsafeBitCast(UInt8(truncatingBitPattern: $0),T.self) } case 2: cast = { unsafeBitCast(UInt16(truncatingBitPattern: $0),T.self) } case 4: cast = { unsafeBitCast(UInt32(truncatingBitPattern: $0),T.self) } case 8: cast = { unsafeBitCast(UInt64($0),T.self) } default: fatalError("cannot be here") } var i = 0 return GeneratorOf { let next = cast(i) return next.hashValue == i++ ? next : nil } }
基本思想是:
>枚举的内存表示 – 不包括关联类型的枚举 – 只是案例的索引,当案例的计数为2 … 256时,它与UInt8相同,当257 … 65536时,它的UInt16等。所以,它可以是unsafeBitcast从相应的无符号整数类型。
> .hashValue的枚举值与大小写的索引相同。
>从无效索引位被转换的枚举值的.hashValue为0
添加:
修正Swift2和实施从@Kametrixom’s answer的投票想法
func iterateEnum<T: Hashable>(_: T.Type) -> AnyGenerator<T> { var i = 0 return anyGenerator { let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory } return next.hashValue == i++ ? next : nil } }
添加:
修正Swift3
func iterateEnum<T: Hashable>(_: T.Type) -> AnyIterator<T> { var i = 0 return AnyIterator { let next = withUnsafePointer(to: &i) { $0.withMemoryRebound(to: T.self,capacity: 1) { $0.pointee } } if next.hashValue != i { return nil } i += 1 return next } }