Optional Return vs throws: Pick One

Swift 2 provides a number of ways to indicate a problem in a method that returns a value, but the two most common are optional return values and throwing errors. Which you choose comes down to your requirements for a particular function, which I will discuss below. But if you take nothing else away from this post, take this: Don’t use both!

That is not to say you can’t use both approaches in your app, just don’t use them both in a single function.

Optional Returns

Pros: Simple to write, simple to handle
Cons: Uninformative

The most common method for indicating failure in a function that returns a value is to make that value optional and return nil when a problem occurs that prevents the successful completion of the function. This has been available since Swift 1.0 and the language has a lot of syntactical features to allow you to efficiently detect and handle nil responses.

Optional returns should be your first choice when all you care about is whether or not a value was returned from a function, not why the function may have failed.

Example:

[gist https://gist.github.com/JoshuaSullivan/c0dc873c7d48cee1c1c4 file=”OptionalReturn.swift”]

Throwing Functions

Pros: Informative errors allow robust recovery options, non-optional return values
Cons: More verbose syntax to handle errors (if you don’t just ignore them with try?)

Swift 2 introduced a robust error handling mechanism to Swift. Functions marked with throws can throw errors which calling objects must explicitly handle or ignore. Having a well-defined set of errors allows calling objects to implement an intelligent recovery plan in the event of a failure, such as correcting erroneous input and trying again. The down-side is that writing error handling code gets verbose, with the do-catch blocks.

Example:

[gist https://gist.github.com/JoshuaSullivan/c0dc873c7d48cee1c1c4 file=”ThrowingFunction.swift”]

Combining Optional Returns and Errors

Don’t! If you don’t want to bother with errors, then your method should just return an optional value. If you do go to the effort of adding errors, let them communicate problems and guarantee a non-nil return value from your function. If the calling object doesn’t want to handle the errors, it can simply invoke your function with try? and treat the return value as optional. If the calling function does handle the errors, allow it to forgo the extra steps of handling optional return values.

Just how expensive is creating an NSDateFormatter?

One of the many mantras that is drilled into iOS devs is that you shouldn’t recreate expensive, complex objects like formatters every time you need them. Instead, keep them around in a static or instance variable and use them as needed. To test this, I created a playground and put this file in the Sources folder:

[gist https://gist.github.com/JoshuaSullivan/6c0d0134e66c60c6cd8c file=”FormatterTest.swift”]

I didn’t put the code directly into the playground because doing ANYTHING in a playground 100k times is going to take a very long time and not be very representative of real-world conditions.

Here’s the playground code, which simply invokes the tests and records the results:

[gist https://gist.github.com/JoshuaSullivan/6c0d0134e66c60c6cd8c file=”Playground.swift”]

The results were unequivocal: creating an NSDateFormatter each time you need to use it is roughly 9x slower than creating it once and using it repeatedly. That said, this is only likely to be an issue for tasks where there is a lot of date formatting going on, such as in a table view with dates in every cell. If you have a situation where you only need to format a single date infrequently (today’s date in a page header, for example), then you shouldn’t worry about hanging on to the date formatter; even though it’s heavy, it only takes a tiny fraction of a second to instantiate one.

CONVENTIONAL WISDOM: CONFIRMED

Addendum: At the request of a coworker (@rexeisen), I added in a test of the static NSDateFormatter.
localizedStringFromDate(_:dateStyle:timeStyle:)
test. As you can see, the results are no better than creating an instance each time. That said, it would be more convenient to use for 1-off formatting tasks, where keeping the formatter around is unnecessary.

Addendum II (2016-01-15): Further testing has revealed that changing the timeStyle and dateStyle of an NSDateFormatter is tremendously expensive. Even more so than just creating a new formatter for each use! Across several trials, performance using a single NSDateFormatter that is re-parameterized on each use was 10% slower than creating a new formatter each time and a full 10x slower than using a single, pre-configured formatter. The take away here is, create a formatter for each repeating case, don’t try to make a single shared formatter do all the work.

Using didSet to configure IBOutlet views…

Swift’s didSet property observer is a great way to configure views linked via IBOutlet. It allows you to set properties that need to be dynamic at runtime or that can’t be configured via Interface Builder:

[gist https://gist.github.com/JoshuaSullivan/80e8d53505dbe2f0868f file=”DidSetExample.swift”]

However, it’s worth keeping a simple rule in mind when you go about configuring your views with didSet:

Don’t reference other IBOutlet views or implicitly unwrapped properties in your didSet block.

The reason for this is simple: you have no way of knowing which order your IBOutlets will be set in, so the other view or property you’re trying to access may not be there. At best, you’re going to be nil-checking a lot and end up only partially configuring your views, requiring follow-up elsewhere in code. At worst, you’re going to accidentally force-unwrap a nil and crash your app.

It’s okay to reference external objects, as seen in the call to the StyleManager above, as long as they’re non-optional and not subject to race conditions. The proper place to establish things like view layout relationships or properties from one view that copy the properties from another is still in viewDidLoad.

Avoid [unowned self] whenever possible!

One of the confusing aspects of Swift is how capture semantics work with closures. When used improperly, they can result in retain cycles or crash the app with the dreaded EXC_BAD_ACCESS. It is worth keeping in mind that capture semantics only apply to reference-based objects (classes); value objects can be used freely without worrying about this. The situation I’ll be looking at here is the capture of self, which is far-and-away the most common situation.

Many asynchronous processes such as API calls include a completion closure, and the most common way to provide it is as an inline closure. In this example, we’re storing the API request object that is created by the call to our API client so that we can allow the user to cancel the request if it’s taking too long. Let’s assume this code appears in our LoginViewController class.

[gist https://gist.github.com/JoshuaSullivan/34cdb4315d79b0a1d85d file=”ForgotCaptureSemantics.swift”]

Whoops! The compiler is mad at us because we have calls to other methods in the class which have an implicit self in front of them. Swift requires that you be explicit about capturing references to objects to avoid unexpected behavior. Fine, let’s add self:

[gist https://gist.github.com/JoshuaSullivan/34cdb4315d79b0a1d85d file=”StrongCaptureSemantics.swift”]

Better! However, the closure is now holding a strong reference to self and the LoginViewController is holding a strong reference to the closure. This creates a retain cycle and will cause the LoginViewController to be kept alive, even if the user navigates away from this screen. Even if the login was successful and the completion closure was invoked, it still exists and maintains its capture of self unless you explicitly nil the reference as part of the completion. We don’t want to go leaking view controllers all willy-nilly, so let’s try that [unowned self] thing we saw in some WWDC video:

[gist https://gist.github.com/JoshuaSullivan/34cdb4315d79b0a1d85d file=”UnownedCaptureSemantics.swift”]

Right, now we definitely don’t have a strong reference to self! However, users are reporting the app is crashing when login is taking too long and they leave the screen before it completes. Looking at the crash logs, you see a rash of EXC_BAD_ACCESS events occurring. Because you declared self was unowned, it was deallocated when the users left the screen, but when the API call completed, it attempted to call the methods referenced in the closure to disastrous effect.

Using unowned as a capture semantic is the equivalent of force-unwrapping an optional. It’s never a great idea and should only be done when you are 100% sure there’s no chance the captured object will be deallocated before it is invoked. When you’re dealing with long-running asynchronous tasks like API requests, this is a bad bet unless the originating class is a singleton or some other pattern which will guarantee the object exists for the lifetime of the app.

For all other cases, consider this pattern using weak capture semantics:

[gist https://gist.github.com/JoshuaSullivan/34cdb4315d79b0a1d85d file=”WeakCaptureSemantics.swift”]

The secret sauce is line 4, where we guard against the possibility that the LoginViewController was deallocated prior to the API request completing. If self no longer exists, it doesn’t care about the API result, and we can bail out of the closure right away. We simply use the strongSelf reference for the remainder of the closure to avoid unwrapping self at every step and we’re good to go!

Why you shouldn’t mourn the removal of –, ++ and C-style for loops from Swift

One of the neatest things about Swift going open-source earlier this year is that the deliberation process for the future of the language, including breaking changes to the syntax, is out in the open. Case in point are the two accepted proposals to remove the unary -- and ++ operators and to remove C-style for loops.

The case against — and ++

View the proposal.

Chris Lattner, the principle architect of Swift, has stated in the past that the ++ and -- operators were added very early in Swift’s inception simply because Objective-C had them. Now that Swift has had a chance to mature, there are a few factors which indicate they are a poor fit for the language. First and foremost is that they are confusing as hell to programmers who haven’t already spent time banging their heads against them in one of the C-derived programming languages. Consider this case:

[gist https://gist.github.com/JoshuaSullivan/72cfabb9ac63aa2721d5 file=”IncrementDecrementExample.swift” /]

The trailing versions of these operators are particularly confusing, where the value is being returned prior to being changed. This difference in pre- and post-incrimenting of the variable is a particularly fruitful source of errors in code, with things like index values going out of range or holding unexpected values because the wrong operator was used.

The strongest case for keeping them is their brevity, but Swift does not favor brevity over security and, as Chris Lattner points out, the more expressive n += 1 is hardly an onerous amount of typing. The main use for the operators seems to be in C-style for loops (based on a survey of Swift-based GitHub projects). Thus, with the imminent removal of those for loops from the language, the main use-case for the operators will die with them.

The case against C-style for loops

View the proposal.

The C-style for loop, like the unary increment and decrement operators, were added early in Swift’s development simply because Objective-C had them. As Erica Sadun so eloquently points out in her proposal, they’re a hold-over from an earlier era of programming and have a complex and error-prone syntax. They accomplish nothing which can’t be accomplished in a more succinct and expressive fashion using the Swift for in loop. Consider these two examples, both of which combine strings from an array to a base string and prints them out:

C-style for loop
[gist https://gist.github.com/JoshuaSullivan/72cfabb9ac63aa2721d5 file=”CForLoopExample.swift” /]

Note that the for loop syntax is completely non-expressive. There’s no indication of what each of the “;”-separated fields aims to accomplish…you have to already be familiar with it.

Swift map() function
[gist https://gist.github.com/JoshuaSullivan/72cfabb9ac63aa2721d5 file=”MapExample.swift” /]

“But wait,” you might say, “I need the index value as well!” There are a couple of ways to do it in Swift without relying on C-style for loops:

Method 1: enumerate()
The handy enumerate() method is present on all collections conforming to SequenceType is one way:
[gist https://gist.github.com/JoshuaSullivan/72cfabb9ac63aa2721d5 file=”EnumerateExample.swift” /]

Method 2: for-in over a Range
[gist https://gist.github.com/JoshuaSullivan/72cfabb9ac63aa2721d5 file=”IterateRangeExample.swift” /]

The 2nd method is stylistically closest to the C-style for loop, but it is still much easier to understand what values i will hold and isn’t subject the problem of a statement inside the for loop modifying the index and causing it to go out of bounds (i is constant).

Conclusion

It can feel a little jarring to lose language features, but with some thought it is clear to see that the removal of these 2 features will result in a language that is more expressive and less error prone.

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:

[gist https://gist.github.com/JoshuaSullivan/cb6d0c6dcfde3f20b43b file=”EnumExample.swift” /]

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:

[gist https://gist.github.com/JoshuaSullivan/cb6d0c6dcfde3f20b43b file=”StructExample.swift” /]

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

[gist https://gist.github.com/JoshuaSullivan/cb6d0c6dcfde3f20b43b file=”Usage.swift” /]

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.

[gist https://gist.github.com/JoshuaSullivan/dbbe909dd08a0fbadb92 file=”Old Output Snippet.swift” /]

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:

[gist https://gist.github.com/JoshuaSullivan/dbbe909dd08a0fbadb92 file=”New Output Snippet.swift” /]

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.