Bagaimana cara saya mendapatkan hitungan dari Swift enum?

Jawaban:

173

Pada Swift 4.2 (Xcode 10) Anda dapat mendeklarasikan kesesuaian dengan CaseIterableprotokol, ini berfungsi untuk semua enumerasi tanpa nilai terkait:

enum Stuff: CaseIterable {
    case first
    case second
    case third
    case forth
}

Jumlah kasus sekarang hanya diperoleh dengan

print(Stuff.allCases.count) // 4

Untuk informasi lebih lanjut, lihat

Martin R
sumber
1
Dalam versi terbaru dari swift, kesalahan melemparnya "Ketik 'DAFFlow' tidak sesuai dengan protokol 'RawRepresentable'". Mengapa itu memaksa saya untuk mengikuti itu? Ada ide?
Satyam
@ Satyam: Apa itu DAFFlow?
Martin R
maaf saya lupa menyebutkan bahwa "DAFFlow 'adalah enum sederhana yang tidak diwarisi dari protokol lain.
Satyam
1
Ini adalah solusi terbaik, tetapi hanya untuk kejelasan - pengembang Apple hanya akan benar-benar dapat mulai menggunakan ini setelah Xcode 10 (dan karenanya Swift 4.2) keluar dari beta (sehingga kemungkinan sekitar 14 September 2018).
JosephH
1
@DaniSpringer: Anda akan menemukan detail berdarah di github.com/apple/swift-evolution/blob/master/proposals/… . Tetapi biasanya Anda tidak memerlukan tipe itu secara eksplisit, karena inferensi tipe otomatis dari kompiler.
Martin R
143

Saya memiliki posting blog yang lebih detail tentang hal ini, tetapi selama tipe mentah enum Anda adalah bilangan bulat, Anda dapat menambahkan hitungan dengan cara ini:

enum Reindeer: Int {
    case Dasher, Dancer, Prancer, Vixen, Comet, Cupid, Donner, Blitzen
    case Rudolph

    static let count: Int = {
        var max: Int = 0
        while let _ = Reindeer(rawValue: max) { max += 1 }
        return max
    }()
}
Nate Cook
sumber
16
Meskipun bagus karena Anda tidak perlu meng-hardcode suatu nilai, ini akan membuat setiap nilai enum setiap kali dipanggil. Itu adalah O (n) bukan O (1). :(
Code Commander
4
Ini adalah solusi yang bagus untuk Int. Saya lebih suka sedikit modifikasi. Ubah properti count statis menjadi countCases metode statis () dan tetapkan ke caseCount konstan statis yang malas dan meningkatkan kinerja dengan panggilan berulang.
Tom Pelaia
2
@ShamsAhmed: Mengkonversi var yang dikomputasi menjadi yang statis.
Nate Cook
3
Bagaimana jika Anda melewatkan beberapa nilai di enum? misalnya case A=1, B=3?
Sasho
2
Ada 2 asumsi selain enummemiliki Intnilai mentah yang Anda lupa sebutkan: Swift enum dengan nilai mentah Int tidak harus mulai dari 0 (meskipun itu adalah perilaku default) dan nilai mentahnya dapat berubah-ubah, mereka tidak memiliki bertambah 1 (meskipun itu adalah perilaku default).
Dávid Pásztor
90

Pembaruan Xcode 10

Mengadopsi CaseIterableprotokol dalam enum, ia menyediakan allCasesproperti statis yang berisi semua kasus enum sebagai a Collection. Cukup gunakan countpropertinya untuk mengetahui berapa banyak kasus yang dimiliki oleh enum.

Lihat jawaban Martin sebagai contoh (dan lebih baik jawabnya daripada jawabanku)


Peringatan : metode di bawah ini sepertinya tidak berfungsi lagi.

Saya tidak mengetahui adanya metode generik untuk menghitung jumlah kasus enum. Namun saya perhatikan bahwa hashValueproperti dari kasus enum adalah tambahan, mulai dari nol, dan dengan urutan yang ditentukan oleh urutan di mana kasus tersebut dinyatakan. Jadi, hash enum terakhir ditambah satu sesuai dengan jumlah kasus.

Misalnya dengan enum ini:

enum Test {
    case ONE
    case TWO
    case THREE
    case FOUR

    static var count: Int { return Test.FOUR.hashValue + 1}
}

count mengembalikan 4.

Saya tidak bisa mengatakan apakah itu aturan atau jika itu akan berubah di masa depan, jadi gunakan dengan risiko Anda sendiri :)

Antonio
sumber
48
Hidup dengan fitur tidak berdokumen, mati oleh fitur tidak berdokumen. Saya suka itu!
Nate Cook
9
Kita seharusnya tidak benar-benar bergantung pada hashValueshal-hal ini; yang kami tahu hanyalah beberapa nilai unik acak - dapat berubah dengan sangat mudah di masa mendatang tergantung pada beberapa detail implementasi kompiler; tetapi secara keseluruhan, kurangnya fungsionalitas penghitungan bawaan mengganggu.
Zorayr
16
Jika Anda tidak keberatan mengatur secara eksplisit case ONE = 0, Anda dapat menggantinya hashValuedengan rawValue.
Kevin Qi
3
yang menjadi perhatian di sini adalah penggunaan properti hashValue yang tidak terdokumentasi, jadi saran saya adalah menggunakan properti yang didokumentasikan dari rawValue.
Kevin Qi
7
Anda telah membuat hardcode fakta bahwa konstanta adalah nilai tertinggi, Lebih baik dan lebih aman untuk hanya menggunakan sesuatu seperti static var count = 4daripada meninggalkan takdir Anda dalam nasib implementasi Swift
Dale yang akan datang
72

Saya mendefinisikan protokol yang dapat digunakan kembali yang secara otomatis melakukan perhitungan kasus berdasarkan pendekatan yang diposting oleh Nate Cook.

protocol CaseCountable {
    static var caseCount: Int { get }
}

extension CaseCountable where Self: RawRepresentable, Self.RawValue == Int {
    internal static var caseCount: Int {
        var count = 0
        while let _ = Self(rawValue: count) {
            count += 1
        }
        return count
    }
}

Maka saya dapat menggunakan kembali protokol ini misalnya sebagai berikut:

enum Planet : Int, CaseCountable {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}
//..
print(Planet.caseCount)
Tom Pelaia
sumber
1
Bagus dan elegan, harus diterima sebagai jawaban IMHO
shannoga
1
mungkin lebih baik untuk mengubah count++ke count+=1karena ++notasi akan dihapus di Swift 3
Aladin
1
tidak bisakah hal yang sama dilakukan hanya dengan static var caseCount: Int { get }? mengapa perlu untuk itu static func?
pxpgraphics
Bagaimana jika Anda melewatkan beberapa nilai di enum? misalnya case A=1, B=3?
Sasho
1
@ Sasho, maka itu tidak akan berhasil. Ini mengharuskan kasing Anda untuk memulai 0dan tidak memiliki celah.
NRitH
35

Buat array allValues ​​statis seperti yang ditunjukkan dalam jawaban ini

enum ProductCategory : String {
     case Washers = "washers", Dryers = "dryers", Toasters = "toasters"

     static let allValues = [Washers, Dryers, Toasters]
}

...

let count = ProductCategory.allValues.count

Ini juga membantu ketika Anda ingin menghitung nilai, dan berfungsi untuk semua tipe Enum

david72
sumber
Meskipun tidak seanggun solusi ekstensi dan sangat manual, saya percaya ini adalah yang paling berguna karena menawarkan lebih banyak daripada yang dihitung. Ini memberi Anda urutan nilai dan daftar semua nilai.
Nader Eloshaiker
2
Anda juga bisa menambahkan hitungan ke enum dengan melakukan static let count = allValues.count. Maka Anda bisa menjadikannya allValuespribadi jika diinginkan.
ThomasW
15

Jika implementasi tidak memiliki masalah terhadap penggunaan integer enums, Anda bisa menambahkan nilai anggota tambahan yang dipanggil Countuntuk mewakili jumlah anggota dalam enum - lihat contoh di bawah ini:

enum TableViewSections : Int {
  case Watchlist
  case AddButton
  case Count
}

Sekarang Anda bisa mendapatkan jumlah anggota dalam enum dengan menelepon, TableViewSections.Count.rawValueyang akan mengembalikan 2 untuk contoh di atas.

Saat Anda menangani enum dalam pernyataan pergantian, pastikan untuk melontarkan pernyataan kegagalan saat bertemu dengan Countanggota di mana Anda tidak mengharapkannya:

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  let currentSection: TableViewSections = TableViewSections.init(rawValue:section)!
  switch(currentSection) {
  case .Watchlist:
    return watchlist.count
  case .AddButton:
    return 1
  case .Count:
    assert(false, "Invalid table view section!")
  }
}
Zorayr
sumber
Saya suka solusi itu karena ia mengubah hitungan secara otomatis ketika menambahkan lebih banyak nilai enum. Namun perlu diingat bahwa ini hanya berfungsi ketika Nilai mentah enum mulai dengan 0.
joern
2
Setuju, ada dua batasan: harus berupa bilangan bulat enum dan harus dimulai dari nol dan dilanjutkan secara bertahap.
Zorayr
3
Saya pikir seluruh poin dari enums Swift yang lebih kuat adalah bahwa kita tidak perlu menggunakan
retas yang
14

Fungsi semacam ini mampu mengembalikan jumlah enum Anda.

Swift 2 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(&i) { UnsafePointer<T>($0).memory }).hashValue != 0 {
        i += 1
    }
    return i
}

Swift 3 :

func enumCount<T: Hashable>(_: T.Type) -> Int {
   var i = 1
   while (withUnsafePointer(to: &i, {
      return $0.withMemoryRebound(to: T.self, capacity: 1, { return $0.pointee })
   }).hashValue != 0) {
      i += 1
   }
      return i
   }
Matthieu Riegler
sumber
3
Ini tidak lagi berfungsi untuk Swift 3. Mencoba mencari implementasi yang tepat, tetapi kosong
Cody Winton
Ini akan sangat unfun untuk debug jika alamat memori berbatasan langsung dengan akhir enumadalah juga Hashable dari jenis yang sama.
NRitH
10

String Enum dengan Index

enum eEventTabType : String {
    case Search     = "SEARCH"
    case Inbox      = "INBOX"
    case Accepted   = "ACCEPTED"
    case Saved      = "SAVED"
    case Declined   = "DECLINED"
    case Organized  = "ORGANIZED"

    static let allValues = [Search, Inbox, Accepted, Saved, Declined, Organized]
    var index : Int {
       return eEventTabType.allValues.indexOf(self)!
    }
}

hitung: eEventTabType.allValues.count

indeks: objeEventTabType.index

Nikmati :)

kalpesh jetani
sumber
10

Oh, hei semuanya, bagaimana dengan unit test?

func testEnumCountIsEqualToNumberOfItemsInEnum() {

    var max: Int = 0
    while let _ = Test(rawValue: max) { max += 1 }

    XCTAssert(max == Test.count)
}

Ini dikombinasikan dengan solusi Antonio:

enum Test {

    case one
    case two
    case three
    case four

    static var count: Int { return Test.four.hashValue + 1}
}

dalam kode utama memberi Anda O (1) plus Anda mendapatkan tes gagal jika seseorang menambahkan enum case fivedan tidak memperbarui implementasi count.

buildsucceeded
sumber
7

Fungsi ini bergantung pada 2 perilaku tidak terdokumentasi saat ini (Swift 1.1) enum:

  • Tata letak memori enumhanya indeks case. Jika jumlah kasus dari 2 hingga 256, itu UInt8.
  • Jika enumbit-casted dari indeks kasus tidak valid , hashValueitu0

Jadi gunakan dengan risiko Anda sendiri :)

func enumCaseCount<T:Hashable>(t:T.Type) -> Int {
    switch sizeof(t) {
    case 0:
        return 1
    case 1:
        for i in 2..<256 {
            if unsafeBitCast(UInt8(i), t).hashValue == 0 {
                return i
            }
        }
        return 256
    case 2:
        for i in 257..<65536 {
            if unsafeBitCast(UInt16(i), t).hashValue == 0 {
                return i
            }
        }
        return 65536
    default:
        fatalError("too many")
    }
}

Pemakaian:

enum Foo:String {
    case C000 = "foo"
    case C001 = "bar"
    case C002 = "baz"
}
enumCaseCount(Foo) // -> 3
rintaro
sumber
Dalam rilis dan aplikasi adhoc akan CRASH
HotJard
Ini berfungsi dalam simulator tetapi tidak pada perangkat 64 bit nyata.
Daniel Nord
5

Saya menulis ekstensi sederhana yang memberikan semua enum di mana nilai mentah adalah countproperti:

extension RawRepresentable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

Sayangnya itu memberikan countproperti ke OptionSetTypetempat itu tidak akan berfungsi dengan baik, jadi di sini adalah versi lain yang membutuhkan kesesuaian eksplisit dengan CaseCountableprotokol untuk enum yang mana kasus yang ingin Anda hitung:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue: IntegerType {
    static var count: Int {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) {
            i = i.successor()
        }
        return Int(i.toIntMax())
    }
}

Ini sangat mirip dengan pendekatan yang diposting oleh Tom Pelaia, tetapi bekerja dengan semua tipe integer.

bzz
sumber
4

Tentu saja, ini tidak dinamis tetapi untuk banyak kegunaan Anda dapat bertahan dengan var statis ditambahkan ke Enum Anda

static var count: Int{ return 7 }

dan kemudian menggunakannya sebagai EnumName.count

Ian Dundas
sumber
3
enum EnumNameType: Int {
    case first
    case second
    case third

    static var count: Int { return EnumNameType.third.rawValue + 1 }
}

print(EnumNameType.count) //3

ATAU

enum EnumNameType: Int {
    case first
    case second
    case third
    case count
}

print(EnumNameType.count.rawValue) //3

* Pada Swift 4.2 (Xcode 10) dapat menggunakan:

enum EnumNameType: CaseIterable {
    case first
    case second
    case third
}

print(EnumNameType.allCases.count) //3
Lê Cường
sumber
2

Untuk kasus penggunaan saya, dalam basis kode di mana banyak orang dapat menambahkan kunci ke enum, dan semua kasus ini harus tersedia di properti allKeys, penting agar allKeys divalidasi terhadap kunci di enum. Ini untuk menghindari seseorang lupa menambahkan kunci mereka ke daftar semua kunci.Mencocokkan jumlah array allKeys (pertama kali dibuat sebagai set untuk menghindari dupes) terhadap jumlah kunci dalam enum memastikan bahwa semuanya ada.

Beberapa jawaban di atas menunjukkan cara untuk mencapai ini di Swift 2 tetapi tidak ada yang berhasil di Swift 3 . Ini adalah versi berformat Swift 3 :

static func enumCount<T: Hashable>(_ t: T.Type) -> Int {
    var i = 1
    while (withUnsafePointer(to: &i) {
      $0.withMemoryRebound(to:t.self, capacity:1) { $0.pointee.hashValue != 0 }
    }) {
      i += 1
    }
    return i
}

static var allKeys: [YourEnumTypeHere] {
    var enumSize = enumCount(YourEnumTypeHere.self)

    let keys: Set<YourEnumTypeHere> = [.all, .your, .cases, .here]
    guard keys.count == enumSize else {
       fatalError("Missmatch between allKeys(\(keys.count)) and actual keys(\(enumSize)) in enum.")
    }
    return Array(keys)
}

Tergantung pada kasus penggunaan Anda, Anda mungkin ingin menjalankan tes dalam pengembangan untuk menghindari overhead menggunakan allKeys pada setiap permintaan

Chris Mitchelmore
sumber
2

Mengapa Anda membuatnya begitu rumit? Penghitung SIMPLEST dari Int enum adalah untuk menambahkan:

case Count

Pada akhirnya. Dan ... biola - sekarang Anda memiliki hitungan - cepat dan sederhana

Dimitar Marinov
sumber
1
Ini a) menambahkan kasus enum asing dan b) tidak akan berfungsi jika jenis mentah enum adalah apa pun selain Int.
Robert Atkins
Ini sebenarnya bukan jawaban yang buruk. Namun, seperti jawaban @Tom Pelaia di atas, ini membutuhkan nilai mentah untuk memulai 0dan tidak memiliki celah dalam urutan.
NRitH
1

Jika Anda tidak ingin mendasarkan kode Anda di enum terakhir, Anda dapat membuat fungsi ini di dalam enum Anda.

func getNumberOfItems() -> Int {
    var i:Int = 0
    var exit:Bool = false
    while !exit {
        if let menuIndex = MenuIndex(rawValue: i) {
            i++
        }else{
            exit = true
        }
    }
    return i
}
Gabriel Araujo
sumber
1

Versi Swift 3 yang bekerja dengan Intenum tipe:

protocol CaseCountable: RawRepresentable {}
extension CaseCountable where RawValue == Int {
    static var count: RawValue {
        var i: RawValue = 0
        while let _ = Self(rawValue: i) { i += 1 }
        return i
    }
}

Kredit: Berdasarkan jawaban oleh bzz dan Nate Cook.

Generic IntegerType(dalam Swift 3 diganti namanya menjadi Integer) tidak didukung, karena ini adalah tipe generik yang sangat terfragmentasi yang tidak memiliki banyak fungsi. successorsudah tidak tersedia lagi dengan Swift 3.

Ketahuilah bahwa komentar dari Code Commander ke Nate Cooks masih valid:

Meskipun bagus karena Anda tidak perlu meng-hardcode suatu nilai, ini akan membuat instantiate setiap nilai enum setiap kali dipanggil. Itu adalah O (n) bukan O (1).

Sejauh yang saya tahu saat ini tidak ada solusi saat menggunakan ini sebagai ekstensi protokol (dan tidak menerapkan di setiap enum seperti Nate Cook lakukan) karena properti tersimpan statis tidak didukung dalam tipe generik.

Bagaimanapun, untuk enum kecil ini seharusnya tidak menjadi masalah. Kasus penggunaan yang khas akan menjadi section.countuntuk UITableViewssebagaimana telah disebutkan oleh Zorayr.

Frederik Winkelsdorf
sumber
1

Memperluas jawaban Matthieu Riegler, ini adalah solusi untuk Swift 3 yang tidak memerlukan penggunaan obat generik, dan dapat dengan mudah dipanggil menggunakan tipe enum dengan EnumType.elementsCount:

extension RawRepresentable where Self: Hashable {

    // Returns the number of elements in a RawRepresentable data structure
    static var elementsCount: Int {
        var i = 1
        while (withUnsafePointer(to: &i, {
            return $0.withMemoryRebound(to: self, capacity: 1, { return 
                   $0.pointee })
        }).hashValue != 0) {
            i += 1
        }
        return i
}
matsoftware
sumber
0

Saya memecahkan masalah ini untuk diri saya sendiri dengan membuat protokol (EnumIntArray) dan fungsi utilitas global (enumIntArray) yang membuatnya sangat mudah untuk menambahkan variabel "Semua" ke enum apa pun (menggunakan swift 1.2). Variabel "semua" akan berisi larik semua elemen di enum sehingga Anda dapat menggunakan all.count untuk penghitungan

Ini hanya bekerja dengan enum yang menggunakan nilai mentah dari tipe Int tetapi mungkin dapat memberikan beberapa inspirasi untuk jenis lainnya.

Ini juga membahas masalah "kesenjangan dalam penomoran" dan "waktu yang berlebihan untuk mengulangi" yang telah saya baca di atas dan di tempat lain.

Idenya adalah untuk menambahkan protokol EnumIntArray ke enum Anda dan kemudian mendefinisikan variabel statis "semua" dengan memanggil fungsi enumIntArray dan menyediakannya dengan elemen pertama (dan yang terakhir jika ada kesenjangan dalam penomoran).

Karena variabel statis hanya diinisialisasi sekali, biaya overhead untuk melewati semua nilai mentah hanya mengenai program Anda sekali.

contoh (tanpa celah):

enum Animals:Int, EnumIntArray
{ 
  case Cat=1, Dog, Rabbit, Chicken, Cow
  static var all = enumIntArray(Animals.Cat)
}

contoh (dengan celah):

enum Animals:Int, EnumIntArray
{ 
  case Cat    = 1,  Dog, 
  case Rabbit = 10, Chicken, Cow
  static var all = enumIntArray(Animals.Cat, Animals.Cow)
}

Berikut kode yang mengimplementasikannya:

protocol EnumIntArray
{
   init?(rawValue:Int)
   var rawValue:Int { get }
}

func enumIntArray<T:EnumIntArray>(firstValue:T, _ lastValue:T? = nil) -> [T]
{
   var result:[T] = []
   var rawValue   = firstValue.rawValue
   while true
   { 
     if let enumValue = T(rawValue:rawValue++) 
     { result.append(enumValue) }
     else if lastValue == nil                     
     { break }

     if lastValue != nil
     && rawValue  >  lastValue!.rawValue          
     { break }
   } 
   return result   
}
Alain T.
sumber
0

Atau Anda bisa mendefinisikan bagian _countluar enum, dan melampirkannya secara statis:

let _count: Int = {
    var max: Int = 0
    while let _ = EnumName(rawValue: max) { max += 1 }
    return max
}()

enum EnumName: Int {
    case val0 = 0
    case val1
    static let count = _count
}

Dengan begitu tidak peduli berapa banyak enum yang Anda buat, itu hanya akan pernah dibuat sekali.

(hapus jawaban ini jika staticmelakukannya)

DI
sumber
0

Metode berikut ini berasal dari CoreKit dan mirip dengan jawaban yang disarankan beberapa orang lain. Ini bekerja dengan Swift 4.

public protocol EnumCollection: Hashable {
    static func cases() -> AnySequence<Self>
    static var allValues: [Self] { get }
}

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

    public static var allValues: [Self] {
        return Array(self.cases())
    }
}

enum Weekdays: String, EnumCollection {
    case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}

Maka Anda hanya perlu menelepon saja Weekdays.allValues.count.

ThomasW
sumber
0
enum WeekDays : String , CaseIterable
{
  case monday = "Mon"
  case tuesday = "Tue"
  case wednesday = "Wed"
  case thursday = "Thu"
  case friday = "Fri"
  case saturday = "Sat"
  case sunday = "Sun"
}

var weekdays = WeekDays.AllCases()

print("\(weekdays.count)")
Nupur Sharma
sumber
-1
struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }
            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().enumCount
    }
}

enum E {
    case A
    case B
    case C
}

E.enumCases() // [A, B, C]
E.enumCount   //  3

tapi hati-hati dengan penggunaan pada jenis non-enum. Beberapa solusi bisa berupa:

struct HashableSequence<T: Hashable>: SequenceType {
    func generate() -> AnyGenerator<T> {
        var i = 0
        return AnyGenerator {
            guard sizeof(T) == 1 else {
                return nil
            }
            let next = withUnsafePointer(&i) { UnsafePointer<T>($0).memory }
            if next.hashValue == i {
                i += 1
                return next
            }

            return nil
        }
    }
}

extension Hashable {
    static func enumCases() -> Array<Self> {
        return Array(HashableSequence())
    }

    static var enumCount: Int {
        return enumCases().count
    }
}

enum E {
    case A
    case B
    case C
}

Bool.enumCases()   // [false, true]
Bool.enumCount     // 2
String.enumCases() // []
String.enumCount   // 0
Int.enumCases()    // []
Int.enumCount      // 0
E.enumCases()      // [A, B, C]
E.enumCount        // 4
JMI
sumber
-1

Itu dapat menggunakan konstanta statis yang berisi nilai terakhir dari enumerasi plus satu.

enum Color : Int {
    case  Red, Orange, Yellow, Green, Cyan, Blue, Purple

    static let count: Int = Color.Purple.rawValue + 1

    func toUIColor() -> UIColor{
        switch self {
            case .Red:
                return UIColor.redColor()
            case .Orange:
                return UIColor.orangeColor()
            case .Yellow:
                return UIColor.yellowColor()
            case .Green:
                return UIColor.greenColor()
            case .Cyan:
                return UIColor.cyanColor()
            case .Blue:
                return UIColor.blueColor()
            case .Purple:
                return UIColor.redColor()
        }
    }
}
93sauu
sumber
-3

Ini kecil, tapi saya pikir solusi O (1) yang lebih baik adalah sebagai berikut ( HANYA jika enum Anda Intmulai dari x, dll.):

enum Test : Int {
    case ONE = 1
    case TWO
    case THREE
    case FOUR // if you later need to add additional enums add above COUNT so COUNT is always the last enum value 
    case COUNT

    static var count: Int { return Test.COUNT.rawValue } // note if your enum starts at 0, some other number, etc. you'll need to add on to the raw value the differential 
}

Jawaban yang dipilih saat ini saya masih percaya adalah jawaban terbaik untuk semua enum, kecuali Anda bekerja dengan itu Intmaka saya merekomendasikan solusi ini.

Drmorgan
sumber
3
Menambahkan nilai ke enum Anda yang sebenarnya tidak mewakili tipe enum adalah bau kode yang buruk. Saya merasa sulit untuk membenarkan termasuk "SEMUA", atau "TIDAK ADA" meskipun kadang-kadang bisa menggoda. Termasuk "COUNT" hanya untuk meretas masalah ini sangat menyebalkan.
Michael Peterson
1
Bau? Jika Anda ingin menyebutnya pasti. Penampil? Iya. Terserah pengembang untuk memutuskan pro dan kontra. Ini sebenarnya jawaban yang sama dengan jawaban Zorayr di atas di mana ia menjelaskan lebih detail tentangnya, dan jawaban yang baru diterima juga serupa. Tetapi sampai Swift menambahkan api untuknya; inilah yang beberapa dari kita telah memutuskan untuk menggunakan. Anda bisa menambahkan fungsi yang memvalidasi nilai enum yang guardmenentang COUNTdan melempar kesalahan, mengembalikan false, dll. Untuk menyelesaikan kekhawatiran Anda tentang representasi tipe.
Drmorgan