We’re in the middle of Apple’s annual product upgrade cycle and this article is the second in a series of tutorials, started last week, meant to highlight the most important new features of Swift 4.2. Today, we’ll look at two two new Swift 4.2 features, the #warning
and #error
compiler directives.
I’ve had a wish list for Swift for quite a while now. Wouldn’t it be nice if we could check for certains conditions at compile time, conditions that we’ve become accustomed to only being able to check at link — even run time? Wouldn’t it be great if we could use the compiler to let other team members know about some aspect of development that is required, but that an individual developer can’t do for another developer? Wouldn’t it be super if we could use the compiler to leave reminders for or send messages to ourselves or other team members?
By providing “Compiler Diagnostic Directives”, we can leverage Swift 4.2’s “#warning
and #error
directives that will cause the Swift compiler to emit a custom warning or an error during compilation.” For more formal descriptions, browse down to “SE-0196” in the official Swift change log master page or go to the exact proposal. Let’s look at each of the scenarios I proposed above and use Swift 4.2’s new features to fulfill our wish list. Please note that some of the following examples are contrived for didactic purposes. The following snippets are not production code. They’re offered to show you what’s now possible with Swift 4.2.
• Let’s say I’m a more junior developer, I wrote some code that works, I have the feeling that some of my code could be optimized, but that I don’t have the time or experience to perform optimizations. So I leave a #warning
, something that will not prevent compilation, but should get the attention of other developers after I check in/push my code. Here’s what the code looks like in Xcode (click to enlarge):
Here’s the code, in text, with color coding — and notes reflecting annotations generated by the Simulator:
1 2 3 4 5 6 7 8 9 10 |
let range = [1,2,3,4,5,6,7,8,9] // [1, 2, 3, 4, 5, 6, 7, 8, 9] #warning("This print algorithm should be optimized.") var index: Int = range.count-1 // 8 while index >= 0 { print(range[index]) // (9 times) index = index - 1 // (9 times) } |
Just for giggles, here’s an optimization that another developer might come up with:
1 2 3 4 |
for i in range.reversed() { print(i) // (9 times) } |
• Suppose my team has two versions of a similar codebase, one for iOS and ARM and one for macOS and Intel. I want to make sure that developers assigned to work on specific platforms do not spend even the slightest amount of time working on the wrong platform. I want Xcode to display one of more #error
flags to grab their attention. In this case, I’ll use the “Conditional Compilation Block” to check for “compilation conditions.” Here’s what the code looks like in Xcode (click to enlarge)…
… and (click to enlarge):
Here’s the code, in text, with color coding — and notes reflecting annotations generated by Xcode:
1 2 3 4 5 6 7 |
#if os(iOS) #error("This project must target ONLY macOS.") // This project must target ONLY macOS. #endif #if arch(arm64) #error("This code can ONLY be built for Intel architectures.") // This code can ONLY be built for Intel architectures. #endif |
• What if a developer must have a unique API key for some service/resource in order to write code for an app you’re in charge of, but you have a limited supply of keys? Whenever you add a new developer to the team, or assign an existing one to work on a module in your code which requires an API key, you want that person to get a big red reminder before they waste any time trying to figure out why he/she can’t run the app. Here’s an example from Xcode (click to enlarge):
CONCLUSION
Seems to me that Swift continues to evolve for the better. Having two levels of compile-time annotations, the #warning
directive for important stuff and #error
directive for urgent stuff, adds to the readability of the Swift language. It also augments inter- and intra-team communications, so the code itself can express preconditions and/or requirements for developers just starting work on a codebase or returning from a hiatus. These directives can also highlight new code just added, new requirements just added, or even new coding styles that the team should adopt.
Remember that you can participate in making Swift a better language: “Contributions to Swift are welcomed and encouraged! Please see the Contributing to Swift guide.”