Bagaimana saya bisa menentukan jumlah kasus dalam Swift enum?
(Saya ingin menghindari penghitungan secara manual melalui semua nilai , atau menggunakan " trik enum_count " yang lama jika memungkinkan.)
Bagaimana saya bisa menentukan jumlah kasus dalam Swift enum?
(Saya ingin menghindari penghitungan secara manual melalui semua nilai , atau menggunakan " trik enum_count " yang lama jika memungkinkan.)
Pada Swift 4.2 (Xcode 10) Anda dapat mendeklarasikan kesesuaian dengan CaseIterable
protokol, 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
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:
sumber
case A=1, B=3
?enum
memilikiInt
nilai 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).Pembaruan Xcode 10
Mengadopsi
CaseIterable
protokol dalam enum, ia menyediakanallCases
properti statis yang berisi semua kasus enum sebagai aCollection
. Cukup gunakancount
propertinya 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
hashValue
properti 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:
count
mengembalikan 4.Saya tidak bisa mengatakan apakah itu aturan atau jika itu akan berubah di masa depan, jadi gunakan dengan risiko Anda sendiri :)
sumber
hashValues
hal-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.case ONE = 0
, Anda dapat menggantinyahashValue
denganrawValue
.static var count = 4
daripada meninggalkan takdir Anda dalam nasib implementasi SwiftSaya mendefinisikan protokol yang dapat digunakan kembali yang secara otomatis melakukan perhitungan kasus berdasarkan pendekatan yang diposting oleh Nate Cook.
Maka saya dapat menggunakan kembali protokol ini misalnya sebagai berikut:
sumber
count++
kecount+=1
karena++
notasi akan dihapus di Swift 3static var caseCount: Int { get }
? mengapa perlu untuk itustatic func
?case A=1, B=3
?0
dan tidak memiliki celah.Buat array allValues statis seperti yang ditunjukkan dalam jawaban ini
Ini juga membantu ketika Anda ingin menghitung nilai, dan berfungsi untuk semua tipe Enum
sumber
static let count = allValues.count
. Maka Anda bisa menjadikannyaallValues
pribadi jika diinginkan.Jika implementasi tidak memiliki masalah terhadap penggunaan integer enums, Anda bisa menambahkan nilai anggota tambahan yang dipanggil
Count
untuk mewakili jumlah anggota dalam enum - lihat contoh di bawah ini:Sekarang Anda bisa mendapatkan jumlah anggota dalam enum dengan menelepon,
TableViewSections.Count.rawValue
yang akan mengembalikan 2 untuk contoh di atas.Saat Anda menangani enum dalam pernyataan pergantian, pastikan untuk melontarkan pernyataan kegagalan saat bertemu dengan
Count
anggota di mana Anda tidak mengharapkannya:sumber
Fungsi semacam ini mampu mengembalikan jumlah enum Anda.
Swift 2 :
Swift 3 :
sumber
enum
adalah jugaHashable
dari jenis yang sama.hitung:
eEventTabType.allValues.count
indeks:
objeEventTabType.index
Nikmati :)
sumber
Oh, hei semuanya, bagaimana dengan unit test?
Ini dikombinasikan dengan solusi Antonio:
dalam kode utama memberi Anda O (1) plus Anda mendapatkan tes gagal jika seseorang menambahkan enum case
five
dan tidak memperbarui implementasicount
.sumber
Fungsi ini bergantung pada 2 perilaku tidak terdokumentasi saat ini (Swift 1.1)
enum
:enum
hanya indekscase
. Jika jumlah kasus dari 2 hingga 256, ituUInt8
.enum
bit-casted dari indeks kasus tidak valid ,hashValue
itu0
Jadi gunakan dengan risiko Anda sendiri :)
Pemakaian:
sumber
Saya menulis ekstensi sederhana yang memberikan semua enum di mana nilai mentah adalah
count
properti:Sayangnya itu memberikan
count
properti keOptionSetType
tempat itu tidak akan berfungsi dengan baik, jadi di sini adalah versi lain yang membutuhkan kesesuaian eksplisit denganCaseCountable
protokol untuk enum yang mana kasus yang ingin Anda hitung:Ini sangat mirip dengan pendekatan yang diposting oleh Tom Pelaia, tetapi bekerja dengan semua tipe integer.
sumber
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
sumber
ATAU
* Pada Swift 4.2 (Xcode 10) dapat menggunakan:
sumber
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 :
Tergantung pada kasus penggunaan Anda, Anda mungkin ingin menjalankan tes dalam pengembangan untuk menghindari overhead menggunakan allKeys pada setiap permintaan
sumber
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
sumber
0
dan tidak memiliki celah dalam urutan.Jika Anda tidak ingin mendasarkan kode Anda di enum terakhir, Anda dapat membuat fungsi ini di dalam enum Anda.
sumber
Versi Swift 3 yang bekerja dengan
Int
enum tipe:Kredit: Berdasarkan jawaban oleh bzz dan Nate Cook.
Generic
IntegerType
(dalam Swift 3 diganti namanya menjadiInteger
) tidak didukung, karena ini adalah tipe generik yang sangat terfragmentasi yang tidak memiliki banyak fungsi.successor
sudah tidak tersedia lagi dengan Swift 3.Ketahuilah bahwa komentar dari Code Commander ke Nate Cooks masih valid:
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.count
untukUITableViews
sebagaimana telah disebutkan oleh Zorayr.sumber
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
:sumber
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):
contoh (dengan celah):
Berikut kode yang mengimplementasikannya:
sumber
Atau Anda bisa mendefinisikan bagian
_count
luar enum, dan melampirkannya secara statis:Dengan begitu tidak peduli berapa banyak enum yang Anda buat, itu hanya akan pernah dibuat sekali.
(hapus jawaban ini jika
static
melakukannya)sumber
Metode berikut ini berasal dari CoreKit dan mirip dengan jawaban yang disarankan beberapa orang lain. Ini bekerja dengan Swift 4.
Maka Anda hanya perlu menelepon saja
Weekdays.allValues.count
.sumber
sumber
tapi hati-hati dengan penggunaan pada jenis non-enum. Beberapa solusi bisa berupa:
sumber
Itu dapat menggunakan konstanta statis yang berisi nilai terakhir dari enumerasi plus satu.
sumber
Ini kecil, tapi saya pikir solusi O (1) yang lebih baik adalah sebagai berikut ( HANYA jika enum Anda
Int
mulai dari x, dll.):Jawaban yang dipilih saat ini saya masih percaya adalah jawaban terbaik untuk semua enum, kecuali Anda bekerja dengan itu
Int
maka saya merekomendasikan solusi ini.sumber
guard
menentangCOUNT
dan melempar kesalahan, mengembalikan false, dll. Untuk menyelesaikan kekhawatiran Anda tentang representasi tipe.