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?