wake-up-neo.net

Xcode 9 und Xcode 10 liefern selbst bei gleicher Swift-Version unterschiedliche Ergebnisse

Ich verwende diesen Code in Xcode 9.3 und Xcode 10 Beta 3-Spielplatz

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

obwohl beide Swift 4.1 verwenden, liefern sie mir unterschiedliche Ergebnisse für die 

auf xcode 9.3 die Größe des Arrays ist 4

und auf xcode 10 beta 3 die Größe des Arrays ist 0

Ich verstehe das überhaupt nicht.

10
kr15hna

Dies ist eine nicht dokumentierte Methode, um eine Sequenz aller Aufzählungswerte zu erhalten. Die Funktion wurde nur in früheren Swift-Versionen verwendet. Es setzt voraus, dass die Hashwerte der Aufzählungswerte aufeinanderfolgende Ganzzahlen sind, beginnend mit Null.

Das funktioniert definitiv nicht mehr mit Swift 4.2 (auch wenn im Swift 4-Kompatibilitätsmodus ausgeführt wird.), Da Hashwerte jetzt immer Randomisiert sind, siehe SE-0206 Hashable Enhancements :

Um Hash-Werte weniger vorhersehbar zu machen, verwendet die Standard-Hash-Funktion standardmäßig einen zufälligen Startwert pro Ausführung.

Sie können das mit überprüfen

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

dabei werden not0 und 1 mit Xcode 10 ausgegeben, jedoch einige andere Werte, die ebenfalls mit jedem Programmlauf variieren.

Eine geeignete Swift 4.2/Xcode 10-Lösung finden Sie unter Wie man eine Aufzählung mit dem String-Typ auflistet? :

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

Wenn Sie hashValue einer Aufzählung verwenden, um Fallwerte (Position oder ID) zu bestimmen, ist dies ein falscher Ansatz, da nicht garantiert wird, dass sequentielle int-Werte, 0,1,2, zurückgegeben werden. Ab Swift 4.2

Beispiel: Wenn Sie eine Aufzählung wie diese verwenden:

enum AlertResultType {
    case ok, cancel 
}

hashValue dieser Aufzählung gibt möglicherweise einen großen int-Wert anstelle von 0 (ok) und 1 (cancel) zurück.

Daher müssen Sie möglicherweise den Aufzählungstyp genauer deklarieren und rowValue verwenden. Zum Beispiel

enum AlertResultType : Int {
    case ok = 0, cancel = 1
}

Die Lösung hierfür ist unten für Xcode 10 und Swift 4.2 und höher.

Schritt 1: Protokoll EnumIterable erstellen.

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
    }
}

Schritt 2: Erweitern Sie das EnumIterator-Protokoll auf Ihr Enum.

enum Colors: String, EnumIterable {
    case red = "Red"
    case yellow = "Yellow"
    case blue = "Blue"
    case green = "Green"
}

Schritt 3: Verwenden Sie die indexValue-Eigenschaft wie hashValue.

Colors.red.indexValue
Colors.yellow.indexValue
Colors.blue.indexValue
Colors.green.indexValue

Beispieldruckanweisung und Ausgabe

print("Index Value: \(Colors.red.indexValue), Raw Value: \(Colors.red.rawValue), Hash Value: \(Colors.red.hashValue)")

Ausgabe: "Indexwert: 0, Rohwert: Rot, Hashwert: 1593214705812839748"

print("Index Value: \(Colors.yellow.indexValue), Raw Value: \(Colors.yellow.rawValue), Hash Value: \(Colors.yellow.hashValue)")

Ausgabe: "Indexwert: 1, Rohwert: Gelb, Hashwert: -6836447220368660818"

print("Index Value: \(Colors.blue.indexValue), Raw Value: \(Colors.blue.rawValue), Hash Value: \(Colors.blue.hashValue)")

Ausgabe: "Indexwert: 2, Rohwert: Blau, Hashwert: -8548080225654293616"

print("Index Value: \(Colors.green.indexValue), Raw Value: \(Colors.green.rawValue), Hash Value: \(Colors.green.hashValue)") 

Ausgabe: "Indexwert: 3, Rohwert: Grün, Hashwert: 6055121617320138804"

0
Amit Gajjar