It has been brought to my attention that there was more use for the unintended values()
functionality that I had outline in my "Other Languages" Java example below.
On the Swift Evolution mailing list, one developer outlined their requirement to loop through an array of enum
case values to add different states to objects.
Another example where a values
array would be useful if the developer wants to do something different for each different case, such as setting an image on a UIButton
subclass for each different UIControlState
Some people have mentioned that perhaps "values" isnt a good term, and suggested that "cases" be a term more suitable to the collection. I would also like to mention that the term "cases" sounds a lot more appropriate and would suggest this over "values" myself. However, for the sake of simplicity, i will keep referring it to "values" for the rest of this proposal.
On the Mailing List, there was some discussion about whether it should be an Array
or a Set
, I think it could depend on the enum
Type. Such as, if it was an Int
it could be an ordered Array
, whereas if it was of type String
perhaps a Set
would be more suitable.
enum SettingsSection : Int {
case Connectivity
case Notifications
case General
static func values() -> [SettingsSection] {
return [.Connectivity, Notifications, General]
}
// or
static let values : [SettingsSection] = [.Connectivity, Notifications, General]
}
for value in SettingsSection.values() {
// Do stuff
}
It's a func
because if it was a var
it wouldnt compile for the reason
Enums may not contain stored properties
But theres also a static let
example in there for too.
Anyway, for the same reasons that we dont want to handle the count
function manually, also having to update this array each time has potential to be out-of-order and potentially unsafe if the enum is being extended by another file.
It’s quite often that I find myself needing to know the size of an enum
.
It’d be really effective in a lot of cases (pun intended) to have some variable/function that returns the total count
of any given enum
. This would reduce the burden of developers to individually manage tasks where the count
is required.
At the time of writing this, one prolific example I can think of is the UITableView
section example, whereas I define the UITableView
sections inside of an enum
declaration and for individual UITableViewDataSource / UITableViewDelegate
.
Like thousands of other developers and myself do is declare an enum
(of type Int
), to define the amount types of sections I'd do within my UITableView
such as the following
enum SettingsSection : Int {
case Connectivity
case Notifications
case General
}
And from here on, most UITableViewDataSource / UITableViewDelegate
protocol functions will require some type of action depending on which section the given section / indexPath.section
. Most of us know this type of pattern when writing Swift code for UITableView
But one gripe we all deal with is the very first UITableViewDataSource
protocol inside of Xcode’s UITableViewController
boilerplate code is the function
func numberOfSectionsInTableView(_ tableView: UITableView) -> Int
This is the most ideal candidate for such a count/cases/length functionality of an enum
. The developer would simply have to call the count
var/function to return an Int
to the value of enum's case count. For example...
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return SettingsSection.count
}
I'm sure there are other applications for including such functionality out-of-the-box for Swift developers, if anyone reading this has any, please let me know so i can append the proposal to include them.
enum SettingsSection : Int {
case Connectivity
case Notifications
case General
case Count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return SettingsSection.Count.rawValue
}
A few of us with experience in C-style languages would have come past this little hacky solution. In C-style languages this would have worked fine too, but because Swift's switch
statements require the developer to exhaust all statements (or use default
) this would add unnecessary bloat to our code base.
Also, because Swift enums can be of types other than Int, this also makes it more redundant within the language.
The best solution for this so far would be to declare a static Int
constant inside the Enum declaration, which would essentially create an elegant solution solve this problem.
enum SettingsSection : Int {
case Connectivity
case Notifications
case General
static let count = 3
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return SettingsSection.count
}
But keep in mind, this is still just a magic number at its core, developers can still unknowingly change this and cause some type of irrational or unexpected behaviour during compile/run time
According to the docs, Java implements a function called length
for its values
property.
SettingsSection.values().length
As you can see, this does require instantiation of the enum
, which would also be an acceptable caveat for such implementation of the feature.
Java Documentation - The best documentation i could find on the net where Java uses its enums that also have a length
function.
Admittedly, the developer has to instantiate an array
containing all the cases of the enum
to get the functionality of the length
function. Even so, it would still be a tiny caveat to having such a great feature within the language.
Perhaps even having the values()
function is what could be used most within Swift, and the count
function could be an added bonus. But at the time of writing this, i have not needed in the past or cannot think of any scenarios where i would iterate through the cases of an enum
.
If anyone reading this has some examples, please let me know so i can append this documenet.
Either way, I believe both scenarios would provide great solutions to significant problems
So by now i feel that i have made a strong enough case for the Swift Evolution team and community to consider making the addition of a count
or even the values()
function within Swift enum
. I look forward to hearing feedback from both parties.
Thanks for your time.
+1 👍