How to Get the Count of a Swift Enum

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

Swift Sample Image 2

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



Leave a reply



Submit