Wie kann ich die Anzahl der Fälle in einer Swift-Aufzählung bestimmen?
(Ich möchte vermeiden, alle Werte manuell aufzulisten oder wenn möglich den alten " enum_count-Trick " zu verwenden.)
Wie kann ich die Anzahl der Fälle in einer Swift-Aufzählung bestimmen?
(Ich möchte vermeiden, alle Werte manuell aufzulisten oder wenn möglich den alten " enum_count-Trick " zu verwenden.)
Ab Swift 4.2 (Xcode 10) können Sie die Konformität mit dem CaseIterable
Protokoll deklarieren. Dies funktioniert für alle Aufzählungen ohne zugehörige Werte:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
Die Anzahl der Fälle wird nun einfach mit ermittelt
print(Stuff.allCases.count) // 4
Weitere Informationen finden Sie unter
Ich habe einen Blog-Beitrag , der ausführlicher darauf eingeht, aber solange der Rohtyp Ihrer Aufzählung eine Ganzzahl ist, können Sie auf diese Weise eine Zählung hinzufügen:
quelle
case A=1, B=3
?enum
einen mitInt
Rohwert , dass Sie vergessen zu erwähnen: Swift Enum ist mit Int Rohwerte nicht über 0 starten (auch wenn das das Standardverhalten) und ihre Ausgangswerte willkürlich können, haben sie nicht um 1 erhöhen (obwohl dies das Standardverhalten ist).Xcode 10 Update
Übernehmen Sie das
CaseIterable
Protokoll in die Aufzählung, es bietet eine statischeallCases
Eigenschaft, die alle Aufzählungsfälle als enthältCollection
. Verwenden Sie einfach seinecount
Eigenschaft, um zu wissen, wie viele Fälle die Aufzählung hat.Ein Beispiel finden Sie in Martins Antwort (und stimmen Sie eher seinen als meinen Antworten zu)
Warnung : Die folgende Methode scheint nicht mehr zu funktionieren.
Mir ist keine generische Methode bekannt, um die Anzahl der Enum-Fälle zu zählen. Ich habe jedoch festgestellt, dass die
hashValue
Eigenschaft der Enum-Fälle inkrementell ist, beginnend bei Null und mit der Reihenfolge, die durch die Reihenfolge bestimmt wird, in der die Fälle deklariert werden. Der Hash der letzten Aufzählung plus eins entspricht also der Anzahl der Fälle.Zum Beispiel mit dieser Aufzählung:
count
gibt 4 zurück.Ich kann nicht sagen, ob dies eine Regel ist oder ob sie sich in Zukunft jemals ändern wird. Verwenden Sie sie daher auf eigenes Risiko :)
quelle
hashValues
bei diesen Dingen nicht wirklich darauf verlassen . Wir wissen nur, dass es sich um einen zufälligen eindeutigen Wert handelt, der sich in Zukunft sehr leicht ändern kann, abhängig von einigen Details der Compiler-Implementierung. Insgesamt ist der Mangel an eingebauter Zählfunktion jedoch störend.case ONE = 0
, können Sie ersetzen Sie dannhashValue
mitrawValue
.static var count = 4
als Ihr Schicksal im Schicksal zukünftiger Implementierungen von SwiftIch definiere ein wiederverwendbares Protokoll, das automatisch die Fallzählung basierend auf dem von Nate Cook veröffentlichten Ansatz durchführt.
Dann kann ich dieses Protokoll beispielsweise wie folgt wiederverwenden:
quelle
count++
,count+=1
da die++
Notation in Swift 3static var caseCount: Int { get }
? warum die Notwendigkeit für diestatic func
?case A=1, B=3
?0
und keine Lücken aufweisen.Erstellen Sie ein statisches allValues-Array wie in dieser Antwort gezeigt
Dies ist auch hilfreich, wenn Sie die Werte auflisten möchten, und funktioniert für alle Aufzählungstypen
quelle
static let count = allValues.count
. Dann können Sie dasallValues
privat machen, wenn Sie gewünscht werden.Wenn die Implementierung nichts gegen die Verwendung ganzzahliger Aufzählungen hat, können Sie einen zusätzlichen Elementwert hinzufügen, der aufgerufen wird
Count
, um die Anzahl der Elemente in der Aufzählung darzustellen - siehe Beispiel unten:Jetzt können Sie die Anzahl der Mitglieder in der Enumeration durch Aufrufen abrufen
TableViewSections.Count.rawValue
. Im obigen Beispiel wird 2 zurückgegeben.Wenn Sie die Aufzählung in einer switch-Anweisung behandeln, stellen Sie sicher, dass ein Assertionsfehler ausgelöst wird, wenn Sie auf das
Count
Mitglied stoßen, bei dem Sie es nicht erwarten:quelle
Diese Art von Funktion kann die Anzahl Ihrer Aufzählung zurückgeben.
Swift 2 :
Swift 3 :
quelle
enum
ist auchHashable
vom gleichen Typ.Anzahl :
eEventTabType.allValues.count
Index :
objeEventTabType.index
Genießen :)
quelle
Oh hey alle zusammen, was ist mit Unit-Tests?
Dies kombiniert mit Antonios Lösung:
Im Hauptcode erhalten Sie O (1) und Sie erhalten einen fehlgeschlagenen Test, wenn jemand einen Enum-Fall hinzufügt
five
und die Implementierung von nicht aktualisiertcount
.quelle
Diese Funktion basiert auf 2 undokumentierten aktuellen (Swift 1.1)
enum
Verhalten:enum
ist nur ein Index voncase
. Wenn die Anzahl der Fälle zwischen 2 und 256 liegt, ist dies der FallUInt8
.enum
aus einem ungültigen Fallindex bitweise umgewandelt wurde ,hashValue
ist es0
Also auf eigenes Risiko verwenden :)
Verwendung:
quelle
Ich habe eine einfache Erweiterung geschrieben, die allen Aufzählungen, bei denen der Rohwert eine Ganzzahl ist, eine
count
Eigenschaft gibt:Leider gibt es die
count
Eigenschaft,OptionSetType
wo es nicht richtig funktioniert, daher ist hier eine andere Version, die eine explizite Konformität mit demCaseCountable
Protokoll für jede Aufzählung erfordert, welche Fälle Sie zählen möchten:Es ist dem von Tom Pelaia veröffentlichten Ansatz sehr ähnlich, funktioniert jedoch mit allen ganzzahligen Typen.
quelle
Natürlich ist es nicht dynamisch, aber für viele Zwecke können Sie mit einer statischen Variable auskommen, die Ihrer Aufzählung hinzugefügt wurde
static var count: Int{ return 7 }
und dann verwenden als
EnumName.count
quelle
ODER
* Auf Swift 4.2 (Xcode 10) kann verwendet werden:
quelle
Für meinen Anwendungsfall ist es in einer Codebasis, in der mehrere Personen einer Aufzählung Schlüssel hinzufügen können und diese Fälle alle in der Eigenschaft allKeys verfügbar sein sollten, wichtig, dass allKeys anhand der Schlüssel in der Aufzählung überprüft wird. Dies soll verhindern, dass jemand vergisst, seinen Schlüssel zur Liste aller Schlüssel hinzuzufügen.Durch Abgleichen der Anzahl des allKeys-Arrays (das zuerst als Satz erstellt wurde, um Dupes zu vermeiden) mit der Anzahl der Schlüssel in der Aufzählung wird sichergestellt, dass alle vorhanden sind.
Einige der obigen Antworten zeigen, wie dies in Swift 2 erreicht werden kann, aber in Swift 3 funktioniert keine . Hier ist die Swift 3- formatierte Version:
Abhängig von Ihrem Anwendungsfall möchten Sie den Test möglicherweise nur in der Entwicklung ausführen, um den Aufwand für die Verwendung von allKeys bei jeder Anforderung zu vermeiden
quelle
Warum machst du das alles so komplex? Der EINFACHSTE Zähler von Int enum ist das Hinzufügen von:
case Count
Schlussendlich. Und ... Bratsche - jetzt haben Sie die Zählung - schnell und einfach
quelle
0
und dürfen keine Lücken in der Sequenz aufweisen.Wenn Sie Ihren Code nicht auf der letzten Aufzählung basieren möchten, können Sie diese Funktion in Ihrer Aufzählung erstellen.
quelle
Eine Swift 3- Version, die mit
Int
Typaufzählungen arbeitet:Credits: Basierend auf den Antworten von bzz und Nate Cook.
Generic
IntegerType
(in Swift 3 umbenannt inInteger
) wird nicht unterstützt, da es sich um einen stark fragmentierten generischen Typ handelt, dem viele Funktionen fehlen.successor
ist mit Swift 3 nicht mehr verfügbar.Beachten Sie, dass der Kommentar von Code Commander zur Antwort von Nate Cooks weiterhin gültig ist:
Soweit ich weiß, gibt es derzeit keine Problemumgehung, wenn Sie diese als Protokollerweiterung verwenden (und nicht wie Nate Cook in jeder Aufzählung implementieren), da statische gespeicherte Eigenschaften in generischen Typen nicht unterstützt werden.
Auf jeden Fall sollte dies für kleine Aufzählungen kein Problem sein. Ein typischer Anwendungsfall wäre die
section.count
fürUITableViews
wie bereits von Zorayr erwähnt.quelle
Erweiterung der Antwort von Matthieu Riegler: Dies ist eine Lösung für Swift 3 , für die keine Generika erforderlich sind. Sie kann einfach mit dem Aufzählungstyp aufgerufen werden mit
EnumType.elementsCount
:quelle
Ich habe dieses Problem für mich selbst gelöst, indem ich ein Protokoll (EnumIntArray) und eine globale Dienstprogrammfunktion (enumIntArray) erstellt habe, mit denen es sehr einfach ist, einer Aufzählung eine "All" -Variable hinzuzufügen (mit swift 1.2). Die Variable "all" enthält ein Array aller Elemente in der Aufzählung, sodass Sie all.count für die Zählung verwenden können
Es funktioniert nur mit Aufzählungen, die Rohwerte vom Typ Int verwenden, kann aber möglicherweise Inspiration für andere Typen liefern.
Es befasst sich auch mit den Problemen "Nummerierung" und "übermäßiger Zeit zum Iterieren", die ich oben und anderswo gelesen habe.
Die Idee ist, das EnumIntArray-Protokoll zu Ihrer Aufzählung hinzuzufügen und dann eine statische Variable "all" zu definieren, indem Sie die Funktion enumIntArray aufrufen und das erste Element (und das letzte, wenn es Lücken in der Nummerierung gibt) bereitstellen.
Da die statische Variable nur einmal initialisiert wird, trifft der Aufwand für das Durchlaufen aller Rohwerte Ihr Programm nur einmal.
Beispiel (ohne Lücken):
Beispiel (mit Lücken):
Hier ist der Code, der es implementiert:
quelle
Oder Sie können einfach die
_count
Außenseite der Aufzählung definieren und statisch anhängen:Auf diese Weise wird die Anzahl der von Ihnen erstellten Aufzählungen immer nur einmal erstellt.
(Löschen Sie diese Antwort, wenn dies der
static
Fall ist.)quelle
Die folgende Methode stammt von CoreKit und ähnelt den Antworten, die einige andere vorgeschlagen haben. Dies funktioniert mit Swift 4.
Dann müssen Sie nur noch anrufen
Weekdays.allValues.count
.quelle
quelle
Seien Sie jedoch vorsichtig bei der Verwendung mit Nicht-Enum-Typen. Einige Problemumgehungen könnten sein:
quelle
Es kann eine statische Konstante verwendet werden, die den letzten Wert der Aufzählung plus eins enthält.
quelle
Dies ist geringfügig, aber ich denke, eine bessere O (1) -Lösung wäre die folgende ( NUR, wenn Ihre Aufzählung
Int
bei x usw. beginnt):Die aktuell ausgewählte Antwort ist meines Erachtens immer noch die beste Antwort für alle Aufzählungen. Wenn Sie nicht mit
Int
dieser Antwort arbeiten, empfehle ich diese Lösung.quelle
guard
gegen denCOUNT
ein Fehler ausgegeben wird, der false zurückgibt usw., um Ihr Problem der Darstellung von Typen zu lösen.