我在这两个的Xcode 9.3和Xcode的10 Beta 3的操场上运行此代码
import Foundation
public protocol EnumCollection: Hashable {
static func cases() -> AnySequence<Self>
}
public extension EnumCollection {
public static func cases() -> AnySequence<Self> {
return AnySequence { () -> AnyIterator<Self> in
var raw = 0
return AnyIterator {
let current: Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: self, capacity: 1) { $0.pointee } }
guard current.hashValue == raw else {
return nil
}
raw += 1
return current
}
}
}
}
enum NumberEnum: EnumCollection{
case one, two, three, four
}
Array(NumberEnum.cases()).count
尽管两者都使用SWIFT 4.1他们给我的不同结果
上的xcode 9.3阵列的大小是4
和上xcode的10测试3数组的大小是0
我完全不明白这一点。
这是一个无证的方式来获取所有枚举值的序列,而只有通过与早期版本的雨燕机会合作。它依赖于枚举值是连续的整数,从零开始的哈希值。
这绝对不与雨燕4.2工作了(即使斯威夫特4兼容模式下运行),因为哈希值现在总是随机的,看SE-0206 Hashable Enhancements:
为了使散列值难以预料,标准散列函数默认使用每个执行随机种子。
您可以验证与
print(NumberEnum.one.hashValue)
print(NumberEnum.two.hashValue)
其不打印0
和1
在Xcode 10,但一些其他值这也与每个程序运行而有所不同。
为了正确夫特4.2 / 10的Xcode溶液,见How to enumerate an enum with String type?:
extension NumberEnum: CaseIterable { }
print(Array(NumberEnum.allCases).count) // 4
对此的解决方案是下文的Xcode 10和夫特4.2及以上。
第1步:创建协议EnumIterable。
protocol EnumIterable: RawRepresentable, CaseIterable {
var indexValue: Int { get }
}
extension EnumIterable where Self.RawValue: Equatable {
var indexValue: Int {
var index = -1
let cases = Self.allCases as? [Self] ?? []
for (caseIndex, caseItem) in cases.enumerated() {
if caseItem.rawValue == self.rawValue {
index = caseIndex
break
}
}
return index
}
}
第2步:扩展EnumIterator议定书的枚举。
enum Colors: String, EnumIterable {
case red = "Red"
case yellow = "Yellow"
case blue = "Blue"
case green = "Green"
}
第3步:使用indexValue财产喜欢使用散列值。
Colors.red.indexValue
Colors.yellow.indexValue
Colors.blue.indexValue
Colors.green.indexValue
样本打印语句并输出
print("Index Value: \(Colors.red.indexValue), Raw Value: \(Colors.red.rawValue), Hash Value: \(Colors.red.hashValue)")
输出:“索引值:0,原始值:红,散列值:1593214705812839748”
print("Index Value: \(Colors.yellow.indexValue), Raw Value: \(Colors.yellow.rawValue), Hash Value: \(Colors.yellow.hashValue)")
输出:“索引值:1,原始值:黄色,散列值:-6836447220368660818”
print("Index Value: \(Colors.blue.indexValue), Raw Value: \(Colors.blue.rawValue), Hash Value: \(Colors.blue.hashValue)")
输出:“索引值:2,原始值:蓝色,散列值:-8548080225654293616”
print("Index Value: \(Colors.green.indexValue), Raw Value: \(Colors.green.rawValue), Hash Value: \(Colors.green.hashValue)")
输出:“指标值:3,原始值:绿色,哈希值:6055121617320138804”
如果你使用一个枚举的散列值来确定情况下的值(位置或ID),这是一种错误的做法,因为它并不能保证返回顺序int类型,0,1,2 ......它不再从4.2迅速工作
例如,如果你使用一个枚举这样的:
enum AlertResultType {
case ok, cancel
}
此枚举的散列值可能会返回而不是0(OK)和1(取消)大int值。
所以,你可能需要更精确地声明枚举类型和使用rowValue。例如
enum AlertResultType : Int {
case ok = 0, cancel = 1
}