9

I've got this enum (Xcode 10/Swift 5) in its own file ("MyEnum.swift"):

enum MyEnum: Int, CaseIterable {
    case A = 0
    case B = 1
    case C = 2
    case D = 3
    case E = 4
    //Each case needs its own number and description!

    var description: String {
        switch self {
            case .A:
                return "abc"
            case .B:
                return "bcd"
            case .C:
                return "cde"
            case .D:
                return "def"
            case .E:
                return "efg"
        }
    }
}

... and want to add the descriptions to a PickerView. I know how to set up the functions for the view but I'm now stuck on counting the enum cases and adding the descriptions.

According to the documentation and different questions, adding CaseIterable is supposed to make it possible to call

MyEnum.allCases.count

... but I can only access allCases from within the enum file. From outside (so from my ViewController class) I can only call MyEnum.AllCases, which hasn't got count and, to be honest, I'm not even sure what AllCases returns exactly (it's not a normal array you can use count on).

Adding this code (source) to the enum file at least makes it possible to count the cases:

static let count: Int = {
    var max: Int = 0
    while MyEnum(rawValue: max) != .none { max += 1 }
    return max
}()

...but isn't there supposed to be an easier way to do this with Swift 4.2+?

How do I get a list of the case descriptions to fill my PickerView with (so "abc", "bcd",... - preferably without hardcoding it)?

Neph
  • 1,823
  • 2
  • 31
  • 69

4 Answers4

20

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

enter image description here

I manually needed to write it

Paul T.
  • 4,938
  • 7
  • 45
  • 93
  • I tried typing it directly but it only gave me the `Value of type 'MyEnum' has no member 'allCases'` error. After restarting Xcode `allCases` was actually in the list once, now it's back to only displaying `AllCases`... – Neph Apr 12 '19 at 11:08
  • 1
    @Neph Even though autocomplete only shows `AllCases`, continue to type `allCases` and use it normally. `MyEnum.allCases.count` will surely work from another file, it's just that it doesn't showing up while typing. – staticVoidMan Apr 12 '19 at 11:14
  • Yes, luckily it does work after restarting (Xcode might have been stuck on some error message) but it only suggests it in a specific function. In all the other ones there's only `AllCases` in the list. – Neph Apr 12 '19 at 11:17
  • I just noticed: `rawValue` isn't suggested either, even though it does exist and work. – Neph Apr 12 '19 at 11:39
  • @Neph , so I assume it's a bug of Xcode and it can be solved by just manually typing and restarting Xcode. Could you mark one of the answers as correct? – Paul T. Apr 12 '19 at 12:17
  • @PaulT. It's probably just coincidence that restarting made it work once. I only get the suggestion for `allCases` in a specific function. I haven't tested it with `rawValue` properly yet but there's no suggestion for it in the class I need it in. – Neph Apr 15 '19 at 08:26
  • @uchuugaka Yes, it does – Paul T. Sep 20 '19 at 14:54
  • Thanks for confirming :) I guess it's always the slow pace of the Swift parser keeping up with what's typed… – uchuugaka Nov 05 '19 at 04:36
2

allCases is declared public, so you should be able to access it from another file:

/// A collection of all values of this type.
public static var allCases: Self.AllCases { get }

like this:

let descriptions = MyEnum.allCases.map { $0.description }

Try cleaning the project and rebuild.

Also, if something is not in Xcode's autocomplete list, it doesn't mean that you can't access that thing. Xcode's complete list has a ton of bugs according to my own experience.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • The issue is when you type, you don't see "allCases" option, so one needs to write it manually – Paul T. Apr 12 '19 at 10:56
  • Strange, that what I see https://take.ms/QWmTX , may be it's because I test from Share Extension code, I don't know – Paul T. Apr 12 '19 at 11:00
  • I tried typing it directly but Xcode complained that there's no "member allCases". It's weird, I restarted Xcode and the first time I then tried it, it actually suggested "allCases", now it doesn't anymore. – Neph Apr 12 '19 at 11:06
  • Try cleaning the project by Cmd+Shift+K and then rebuilding it by Cmd+B. @Neph – Sweeper Apr 12 '19 at 11:07
  • @Sweeper Tried that and also restarted again. The behavior is weird, in a specific function in actually suggests the lower case version, in the others it doesn't. – Neph Apr 12 '19 at 11:15
  • I just noticed: `rawValue` isn't suggested either, even though it does exist and work. – Neph Apr 12 '19 at 11:39
0

For the sake of completeness and in case allCases doesn't work at all (even after a restart) add this to the enum file:

static let allValues = [MyEnum.A, MyEnum.B, MyEnum.C, MyEnum.D, MyEnum.E]

It's hardcoded but at least it gives you access to everything:

  • count: MyEnum.allValues.count
  • description (e.g. "abc"): MyEnum.allValues[0].description
  • rawValue (e.g. 0):MyEnum.allValues[0].rawValue
Neph
  • 1,823
  • 2
  • 31
  • 69
  • Don't do this as it creates a dependency on the programmer to keep the cases updated. In case of `CaseIterable` it auto creates `allCases`, and right now it looks like an Xcode issue/limitation that it isn't provided in auto-complete. But rest assured, it will work because it is promised by the protocol. [Read: How CaseIterable Works Internally in Swift](https://swiftrocks.com/how-caseiterable-works-internally-in-swift.html) – staticVoidMan Apr 12 '19 at 12:05
-1

The same issue happened to me. What ended up working is restarting xcode.

Andrew
  • 27
  • 4
  • Which Xcode version? Please look at the other answers, I commented on them: A restart only made it work once, afterwards the suggestion didn't pop up again. – Neph May 25 '20 at 13:14