2015-06-26 5 views
6

zu deklarieren Ich frage mich: Was ist der beste Weg, um eine nicht geordnete Liste von skalaren Werte in Swift, die vollständig durch ein Symbol und wahrscheinlich zu sein, zu deklarieren vom Compiler überprüft?Was ist der beste Weg, um eine Liste von Skalarwerten in Swift

Sagen wir, ich möchte eine Liste der LetterSpacing Werte, die ich in meinem Code über ihre Symbole zugreifen und verwenden möchte, deklarieren.

Mein Verständnis ist, dass ich eine rasche enum wie folgt erklären sollte:

enum LetterSpacing: Double { 
    case Short = 1.0 
    case Medium = 2.0 
    case Large = 3.0 
} 

Das funktioniert gut und wird überprüft Compiler aber das lästige Teil ist, dass ich zu LetterSpacing.XXX.rawValue jedes Mal müssen den zugrunde liegenden Wert zuzugreifen. Die .rawValue stört mich ein bisschen, um das überall angeben zu müssen.

Ich nehme an, es würde keinen Sinn machen oder wäre unangemessen, ein struct mit drei static let Short = 1.0 usw. zu erklären ..

So, wie würden Sie solche Fälle behandeln? Ist es möglich, den vorhandenen Typen eine Art Protokoll/Erweiterung zuzufügen, um die Short Enum als eigenen Wert zu haben? (d. h. let size = LetterSpacing.Short würde vom Typ Double sein und einen Wert von 1.0 haben)

Antwort

6

Die enum wäre aus mehreren Gründen bevorzugt.


Zuerst wird die enum endet tatsächlich mit einem geringeren Speicherbedarf auf. Dies liegt daran, dass Swift enum Werte in ein einzelnes Byte (egal was der Rohwert ist) optimiert, und wir erhalten nur den vollen Wert davon, wenn wir rawValue auf dem enum Wert aufrufen. Fügen Sie den folgenden Code in einen Spielplatz zu sehen:

struct LetterSpacingS { 
    static let Short: Double = 1.0 
} 

enum LetterSpacingE: Double { 
    case Short = 1.0 
} 

sizeofValue(LetterSpacingS.Short) 
sizeofValue(LetterSpacingE.Short) 

Die double ist 8 Bytes, während die enum nur 1.


Zweitens ist die Bedeutung des ersten Punktes erstreckt sich über nur Speicherbedarf . Dies kann auch für die Ausführungseffizienz unseres Programms gelten. Wenn wir zwei Werte von unserer Struktur vergleichen wollen, vergleichen wir 8 Bytes. Wenn wir zwei unserer Enum-Werte vergleichen wollen, vergleichen wir nur ein einzelnes Byte. Wir haben 1/8 so viele Bytes in diesem speziellen Fall zu vergleichen. Und das ist nur mit einem Doppel. Berücksichtigen Sie, dass Swift-Enums auch eine Zeichenkette als Hintergrundtyp haben können. Der Vergleich von zwei Strings kann außerordentlich teuer sein, wenn man nur das einzelne Byte vergleicht, hinter dem sie in einem enum versteckt sind.


Drittens die ENUM verwenden, sind wir den Vergleich nicht Gleitkommazahlen, die Sie wirklich nicht wollen, sprechen im Allgemeinen zu tun.

Viertens gibt uns die Verwendung der enum eine Art von Sicherheit, die wir mit der Konstantenstruktur nicht bekommen können. Die ganze Struktur der Konstanten erlaubt es, eine Handvoll vordefinierter Konstanten zu definieren.

Aber wie würde nun eine Methode aussehen, die einen dieser Werte erwartet?

func setLetterSpacing(spacing: Double) { 
    // do stuff 
} 

Und nun, was passiert, wenn Joe-Coder in kommt und tut:

foo.setLetterSpacing(-27.861) 

Nichts hat ihn zu stoppen. Es braucht ein Double, ein Double. Dies ist vielleicht nicht so häufig, aber wenn Sie sich in einer Bibliothek befinden, die Sie verteilen, lassen Sie sich offen für Fragen und Kommentare wie "Wenn ich einen Wert von 5,0 in passiere, sieht es überhaupt nicht gut aus!"

Aber vergleichen Sie dies mit der Verwendung der enum.

func setLetterSpacing(spacing: LetterSpacing) { 
    // do stuff 
} 

Und jetzt erhalten wir nur die drei vordefinierten Optionen für das, was in dieses Argument übergeben werden soll.

Und außerhalb Ihrer internen Verwendung für die Werte, die von enum gehalten werden, sollten Sie rawValue zu viel verwenden.


Der fünfte Grund ist nicht ein starker Grund für eine ENUM über eine Struktur mit, aber meistens nur ein Punkt zu machen, ist einer der Gründe für die Verwendung einer Struktur über eine Enumeration vorgeschlagen zu beseitigen. Schnelle Enums können in anderen Typen geschachtelt werden, andere Typen können in Swift-Enums verschachtelt werden. Sie müssen keine Struktur verwenden, um verschachtelte Typen zu erhalten.

+0

Das war die Antwort, die ich suchte. Ich war vom ersten Tag an über das Thema Gedächtnis und Effizienz überzeugt. Was ist mit diesem '.rawValue' Typ? Die Lösung, die ich von Ihnen sehe, ist die Neuimplementierung von Funktionen, die 'LetterSpacing'-Typen überall verwenden. In meinem Fall wäre das möglich, weil es einfach zu viel zu tun gibt. Ich erkläre nur einige "globale" "bekannte" Werte, die ich verwenden kann, um beim Erstellen meiner Stile auf den Buchstabenabstand Bezug zu nehmen. Ich kann mir nicht vorstellen, dass ich alle Apple-Setter nur aus Gründen der Klarheit reinimplementiere :) –

+0

Im Grunde genommen sollte man '.rawValue' nur verwenden, wenn man es tatsächlich tatsächlich braucht. Basierend auf "LetterSpacing", wenn wir annehmen, dass es sich um eine Textzeichnung handelt, ziehen Sie '.rawValue' nur heraus, wenn Sie den Text tatsächlich zeichnen. Es spielt an keinem anderen Punkt eine Rolle. Für spezifischere Ratschläge, wie man mit '.rawValue' umgeht, müsste jemand spezifischere Beispiele sehen. – nhgrif

+0

Denken Sie daran, @NicolasB., Sie können immer Erweiterungen zu Apple-Klassen schreiben, die Ihre 'LetterSpacing'-Enumeration (die nur einen angemessenen Wert auf Apples Klassen setzt) ​​verwenden, ohne den Apple-Code neu zu implementieren. – nhgrif

2

Ich sehe nicht, warum das Erstellen eines Struct mit drei statischen Konstanten unangemessen wäre. Ich sehe eine Menge Swift-Code (auch von Apple), der das tut.

Structs können Sie schöne Hierarchien erstellen:

struct Style { 
    struct Colors { 
     static let backgroundColor = UIColor.blackColor() 
     ... 
    } 

    struct LetterSpacing { 
     static let Short = 1.0 
    } 

    ... 
} 
+0

Ich scheint nur "falsch" im Vergleich zu der "enum", die semantisch tut, was ich brauche. Ich muss möglicherweise viele dieser Strukturen deklarieren, um verschiedene visuelle Eigenschaften darzustellen, einige von ihnen können auch verschachtelt sein. Am Ende frage ich mich: "Warum würden Sie hier überhaupt eine Struktur verwenden? Hier ist kein Strukturverhalten nötig". Ich weiß nicht, es fühlt sich an, als würde ich das falsche Werkzeug benutzen. –

+0

Aktualisiert meine Antwort ... – diederikh

+0

Nun, das ist genau das, was ich jetzt habe. Aber ich bin mir ziemlich sicher, dass verschachtelte Typen auch mit 'enum' möglich sind, oder? :) Gibt es irgendeinen Grund, warum ich 'enum' vs' struct' in diesem Fall verwenden sollte? –

Verwandte Themen