How do I get the count of a Swift enum?
As of Swift 4.2 (Xcode 10) you can declare
conformance to the CaseIterable
protocol, this works for all
enumerations without associated values:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
The number of cases is now simply obtained with
print(Stuff.allCases.count) // 4
For more information, see
- SE-0194 Derived Collection of Enum Cases
Enum: Count and list all cases (from outside!)
I tried in 1 file:
enum TestEnum: CaseIterable {
case test1
case test2
}
in another file of another class I wrote:
let count = TestEnum.allCases.count
And it works, but I noticed that when I was typing "allCases" wasn't shown
I manually needed to write it
How to get enum count
You can't.
There is one technique that allows you to get the enum count. It looks like
typedef enum {
value_one,
value_two,
value_three,
...
enum_count
} my_enum;
Now the value enum_count
is the count of values in the enum. However, this technique only works if the enums all carry their implicit value, where value_one
is 0
, value_two
is 1
, etc. Because of this, the last value in the enum always has the value of the count of enum values. In your case, your enum constants have explicit values that are not monotonically incrementing. There is no way to derive a count from this type of enum. And even in the theoretical world where you could derive a count, that wouldn't help you because you could not derive the value of a given enum constant.
How do I get the count of a Swift enum?
As of Swift 4.2 (Xcode 10) you can declare
conformance to the CaseIterable
protocol, this works for all
enumerations without associated values:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
The number of cases is now simply obtained with
print(Stuff.allCases.count) // 4
For more information, see
- SE-0194 Derived Collection of Enum Cases
Get enum parameter value
Inside ButtonType
enum, declare property like this:
enum ButtonType {
...
var value: String {
switch self {
case .number(let number): return number
case .clear(let clearValue): return clearValue
case .backspace(let backSpaceValue): return backSpaceValue
}
}
}
How to enumerate an enum with String type?
Swift 4.2+
Starting with Swift 4.2 (with Xcode 10), just add protocol conformance to CaseIterable
to benefit from allCases
. To add this protocol conformance, you simply need to write somewhere:
extension Suit: CaseIterable {}
If the enum is your own, you may specify the conformance directly in the declaration:
enum Suit: String, CaseIterable { case spades = "♠"; case hearts = "♥"; case diamonds = "♦"; case clubs = "♣" }
Then the following code will print all possible values:
Suit.allCases.forEach {
print($0.rawValue)
}
Compatibility with earlier Swift versions (3.x and 4.x)
If you need to support Swift 3.x or 4.0, you may mimic the Swift 4.2 implementation by adding the following code:
#if !swift(>=4.2)
public protocol CaseIterable {
associatedtype AllCases: Collection where AllCases.Element == Self
static var allCases: AllCases { get }
}
extension CaseIterable where Self: Hashable {
static var allCases: [Self] {
return [Self](AnySequence { () -> AnyIterator<Self> in
var raw = 0
var first: Self?
return AnyIterator {
let current = withUnsafeBytes(of: &raw) { $0.load(as: Self.self) }
if raw == 0 {
first = current
} else if current == first {
return nil
}
raw += 1
return current
}
})
}
}
#endif
Display number of rows in tableview section based on enum from JSON
If you have the items in your enum TypeEnum
in the same order you want your sections (which you already have as it seems) then you can make the enum conform to CaseIterable
which means you can get an array of all items and use that.
enum TypeEnum: String, Codable, CaseIterable {
case article = "article"
case course = "course"
case guide = "guide"
case interview = "interview"
}
Now you can get the count in one line
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.filter { $0.type == TypeEnum.allCases[section]}.count
}
And when creating the cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "sourceCell", for: indexPath) as! SourceCell
let type = TypeEnum.allCases[indexPath.section]
let item = items.filter { $0.type == type }[indexPath.row]
cell.authorLabel.text = item.author
cell.titleLabel.text = item.title
return cell
}
You can also change the section count function to have more future proof code
func numberOfSections(in tableView: UITableView) -> Int {
return TypeEnum.allCases.count
}
Related Topics
How to Dispatch_Sync, Dispatch_Async, Dispatch_After, etc in Swift 3, Swift 4, and Beyond
How to Get a Reference to the App Delegate in Swift
How to Print Double Quotes Inside ""
Changing the Status Bar Color For Specific Viewcontrollers Using Swift in Ios8
Printing a Variable Memory Address in Swift
Instance Member Cannot Be Used on Type of Custom Class
Swift Protocol Inheritance and Protocol Conformance Issue
Usb Connection Delegate on Swift
How Does One Make an Optional Closure in Swift
Xcode 8/Swift 3: Simple Uipicker Code Not Working
Load a Uiview from Nib in Swift
Firestore Search Array Contains For Multiple Values
How to Encode a String to Base64 in Swift