Don’t use Swift enums to contain magic strings!

At first glance, using a Swift enum with a raw type of String seems to be a great way to package (or, if you like, enumerate) magic strings used by things like Notifications:

However, this is a poor application of the Swift enum for the following reason: you are not interested in the enum case, only its raw value. Any place you want to use the magic string in your code you’re forced into fully qualifying the enum case (because the argument type is a string, not the type of your enum) and then accessing the rawValue property.

A better approach is to use a Swift struct with static constant string members defining the magic strings:

The look is very similar to an enum, but in practice it ends up being shorter and cleaner to use:

Now, this argument is moot if you have a situation where methods in your classes take your enum type as an argument and use the rawValue at some point internally, but for things like userInfo dictionary keys, user defaults keys, notification names, segue names, etc. you are better off with the struct approach, since the string is all you’re interested in.

2015-12-16 Addendum:
As with any advice on using Swift, this should not be viewed as an Immutable Truth of the Universe™. There are still situations when an enum would be a perfectly reasonable container for your strings: namely, when you have a model built around the use of the enums and not just the strings they contain.

Better mogenerator Swift Templates

It finally happened that Core Data was required for one of my Swift 2 projects, so naturally I turned to mogenerator to produce my human and machine NSManagedObject subclasses. However, I was unsatisfied with the results of the machine file…particularly, the tendency of the template to clutter up the global namespace with enums for the attributes and relationships. Here’s the default template’s output for an entity named Category with a pair of attributes and one relationship.

As you can see, it creates a pair of public enums to enumerate the names of the attributes and relationships. This isn’t too bad for one or two entities, but gets annoying when you have dozens of entities, each adding 2-4 new global-level types.

Moreover, I have a problem with the use of the enum type. Yes, we are enumerating the possible attributes for this entity, but absolutely nothing in the Core Data framework will accept them; it’s purely string-based. As a result, anywhere you use the enum cases, you’ll have to tack on the .rawValue accessor to get the underlying string. I figured we could do better:

The way I chose to address the first issue is to move the declarations inside the class declaration for the entity. Since Swift supports name-spacing, this means that instead of typing “CategoryAttributes.id”, you’d type “Category.Attributes.id”. This is only 1 more character and it results in only “Category” being added to the global namespace.

The second change I made was to convert the enums to structs with each of the entries being a static let string. The structs are never meant to be instantiated, they simply provide a coherent namespace for our attribute and relationship names.

You can get the updated template files here: https://gist.github.com/JoshuaSullivan/2057f09cc18243a3f2df

More information about using custom mogenerator templates can be found in this Stack Overflow post.