Xcode 9 и Xcode 10 дают разные результаты даже при одинаковой быстрой версии - PullRequest
0 голосов
/ 06 июля 2018

Я использую этот код на игровой площадке 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, они дают мне разные результаты для

on xcode 9.3 размер массива 4

и xcode 10 beta 3 размер массива 0

Я совсем не понимаю.

Ответы [ 3 ]

0 голосов
/ 06 февраля 2019

Решение для этого ниже для Xcode 10 и Swift 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, как при использовании hashValue.

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 голосов
/ 07 мая 2019

Если вы используете hashValue для перечисления для определения значений регистра (position или id), это неправильный подход, поскольку он не гарантирует возврат последовательных значений int, 0,1,2 ... Он больше не работает с свифт 4,2

Например, если вы используете перечисление как это:

enum AlertResultType {
    case ok, cancel 
}

hashValue этого перечисления может возвращать большое значение типа int вместо 0 (нормально) и 1 (отменить).

Так что вам может потребоваться более точно объявить тип enum и использовать rowValue. Например

enum AlertResultType : Int {
    case ok = 0, cancel = 1
}
0 голосов
/ 06 июля 2018

Это недокументированный способ получить последовательность всех значений перечисления, и работал только случайно с более ранними версиями Swift. Опирается на хеш-значения значений перечисления, являющихся последовательными целыми числами, начиная с нуля.

Это определенно больше не работает со Swift 4.2 (даже если запущен в режиме совместимости Swift 4), потому что хэш-значения теперь всегда рандомизированный, см. SE-0206 Расширяемые свойства :

Чтобы сделать хеш-значения менее предсказуемыми, стандартная хеш-функция по умолчанию использует случайное начальное число при выполнении.

Вы можете проверить это с помощью

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

, который не печатает 0 и 1 с Xcode 10, но некоторые другие значения, которые также меняются при каждом запуске программы.

Правильное решение Swift 4.2 / Xcode 10 см. В Как перечислить перечисление со строковым типом? :

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