I'm no enum
expert but I enjoy playing around with them to make my project code easier to read and type safe.
I've written a simple enum to track the selected type (a To-Many relationship property) for a CoreData entity and provide some formatting.
enum Taxon {
case common(name: String)
case genus(name: String)
case species(name: String)
case subspecies(name: String)
case group(name: String)
case cultivar(name: String)
case variety(name: String)
case extended(name: String)
var typeName: String {
switch self {
case .common: return "Common"
case .genus: return "Genus"
case .species: return "Species"
case .subspecies: return "Subspecies"
case .group: return "Group"
case .cultivar: return "Cultivar"
case .variety: return "Variety"
case .extended: return "Taxonomny"
}
}
var formatted: String {
switch self {
case .common(let name): return name.capitalized
case .genus(let name): return name.capitalized
case .species(let name): return name.lowercased()
case .subspecies(let name): return String(format: "ssp. %@", name)
case .group(let name): return String(format: "(%@ Group)", name)
case .cultivar(let name): return String(format: "cv. %@", name)
case .variety(let name): return String(format: "var. %@", name)
case .extended(let name): return name.capitalized
}
}
I could make the enum
an associated type String
but then I lose the ability to include arguments...
Error message - Enum with raw type cannot have cases with arguments
I can parse a Set
of entity instance name
as follows and this provides a perfectly formatted string, based on the var .formatted
in the enum Taxon
.
for name in setSorted {
let nameComp: String = name.component!
let nameType: String = name.type!.name!
var nameFormatted = String()
switch nameType {
case Taxon.common(name: nameType).typeName: nameFormatted = Taxon.common(name: nameComp).formatted
case Taxon.genus(name: nameType).typeName: nameFormatted = Taxon.genus(name: nameComp).formatted
case Taxon.species(name: nameType).typeName: nameFormatted = Taxon.species(name: nameComp).formatted
case Taxon.subspecies(name: nameType).typeName: nameFormatted = Taxon.subspecies(name: nameComp).formatted
case Taxon.group(name: nameType).typeName: nameFormatted = Taxon.group(name: nameComp).formatted
case Taxon.cultivar(name: nameType).typeName: nameFormatted = Taxon.cultivar(name: nameComp).formatted
case Taxon.variety(name: nameType).typeName: nameFormatted = Taxon.variety(name: nameComp).formatted
case Taxon.extended(name: nameType).typeName: nameFormatted = Taxon.extended(name: nameComp).formatted
default: nameFormatted = "E R R O R : Taxon : switch"
}
stringNames.append(nameFormatted)
if setSorted.last != name {
stringNames.append("\(stringBetween)")
}
}
However seems clunky to me. Surely there is more concise / better code?
Elsewhere I have whittled this type of enumeration down to a one liner (to be clear, without the switch
statement), but those one liners were based upon an enum
with an associated type and also did not have (arguments).
For example...
let calendarComponent = EntityDate(rawValue: format)?.calendarComponent
(where EntityDate
is the enum of type NSNumber
and format
is the var
of type NSNumber
, inserted by a func
and used to identify the appropriate calendarComponent
.)
So if I attempt a line code like this...
let test = Taxon(rawValue: nameType)
I am provided with a compiler message...
'Taxon' cannot be constructed because it has no accessible initializers
I've attempted a few ways to prepare an initialiser by copying patterns I have for other enum
but nothing has worked so far and I'd prefer to keep the enum pure (of its own type) so that I can include the argument (name: String)
.
I've wasted a little too much time on this frankly unnecessary obsession, so I am wondering what I am missing?
Where exactly do you get the error message ?
@Claude31 good question... I can't update my original post so I'll add some more information below.
In response to comment by @Claude31, the location of the (second) error message...
let test = Taxon(rawValue: nameType)
where I am attempting to obtain a reference to one of the values in theenum
Taxon
. For clarity, this replaces the commented out code - the above notedswitch
statement in the iteration oversetSorted
. So eventually with an accessible initialiser, I might develop that line of code to replace theswitch
statement entirely and it might look something like this...let test = Taxon(rawValue: nameType).formatted(nameComp)
although I am not sure that syntax is correct. Also for clarity, the first error message "Enum with raw type cannot have cases with arguments" is against the line that declares theenum Taxon: String {...}
(when I attempt to associate a type with the enum).