Xcode中9和10的Xcode给出不同的结果,即使有相同的迅速版

问题描述 投票:10回答:3

我在这两个的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

我完全不明白这一点。

swift xcode xcode10
3个回答
18
投票

这是一个无证的方式来获取所有枚举值的序列,而只有通过与早期版本的雨燕机会合作。它依赖于枚举值是连续的整数,从零开始的哈希值。

这绝对不与雨燕4.2工作了(即使斯威夫特4兼容模式下运行),因为哈希值现在总是随机的,看SE-0206 Hashable Enhancements

为了使散列值难以预料,标准散列函数默认使用每个执行随机种子。

您可以验证与

print(NumberEnum.one.hashValue)
print(NumberEnum.two.hashValue)

其不打印01在Xcode 10,但一些其他值这也与每个程序运行而有所不同。

为了正确夫特4.2 / 10的Xcode溶液,见How to enumerate an enum with String type?

extension NumberEnum: CaseIterable  { }
print(Array(NumberEnum.allCases).count) // 4

1
投票

对此的解决方案是下文的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”


0
投票

如果你使用一个枚举的散列值来确定情况下的值(位置或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
}
© www.soinside.com 2019 - 2024. All rights reserved.