Thinking ahead by looking back: Swift 4 @ WWDC

By Will Braynen

Illustration by Donna Blumenfeld

Illustration by Donna Blumenfeld

Now that we are probably halfway between the Apple Worldwide Developers Conference (WWDC) — this past June — and the upcoming Swift 4 migrations in prod once Xcode 9 comes out of beta, I thought it time to think ahead and revisit June.  Everyone is talking about how easy it will be to deserialize JSONs (so no more SwiftyJson?).  But I won't talk about that.  WWDC 2017 has left a number of great videos in its wake.  All videos of the conference talks are available online.  I am still making my way through them.  Given that, in iOS Land, I work in Swift, my first stop was the "What's New in Swift" talk, where you can also find the presentation slides from which I pulled the code examples below.

To whet your appetite, here are five of the many interesting things from the talk.

 

First interesting thing

# Ruby
one = "\u{E9}"
two = "\u{65}\u{301}"
one.length
two.length
one == two


é
é
1
2
false
 

That's right: (é == é) is false.  Try it for yourself using an online Ruby interpreter.  And yes, this is relevant to Swift 4!

 

Second interesting thing

Imagine the following code:

// Swift (3 cf 4)
let big = downloadHugeString()
let small = extractTinyString(from: big)
mainView.titleLabel.text = small

You might then end up holding on to big memory, even though all you need is small — a tiny subset of big. This would be akin to a memory leak. Assuming extractTinyString is just giving you a reference and so isn't returning a copy, what you should have written, on the last line, is:

mainView.titleLabel.text = String(small)

Making a copy of the string will mean that the big string can be released. The Xcode build system will now be able to detect this and suggest this to you.

 

Third interesting thing

The new build system, rebuilt in Swift, is built on top of an open-source set of libraries: the llbuild engine.  So, if you are curious about what's under the hood or want to build your own, check out the githubs.

And no more "Indexing…" message that, when I first saw it, made me think that it was still building.  Indexing will be done as part of the build process instead of in the background.  And no more duplicate-looking "Build" and "Test" whenever you try to run your unit tests to get code coverage.  Code coverage, if enabled, will just be generated as part of all builds.  These were presented as optimizations made to the build system because, in this kind of case, Apple is typically trying to either (a) make it build faster or (b) shrink the size of the executable.  But I actually see these as important UI/UX improvements to the IDE.

 

Fourth interesting thing

It's the little things. My personal Swift pet peeve: having to use text.characters.count (where text is of type String) when you want to know the length of a string. Expecting a String class to have a length property, I kept adding the same String extension to all my Xcode projects. So finally, in Swift 4, all you need is text.count instead of text.characters.count .

What's more, code like this will build now:

// Swift 4
let asciiTable = zip(65..., "ABCDEFGHIJKLMNOPQRSTUWXYZ")
for (code, character) in asciiTable {
    print(code, character, separator: ": ")
}

And yes, 65... is now legit. In Swift 3, we would have to write this:

// Swift 3.2
let asciiTable = zip(65...90, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters)
for (code, character) in asciiTable {
    print(code, character, separator: ": ")
}

Not only is there now more syntactic sugar for ranges, but strings are collections now.  Collections and sequences of characters.  And depending on your understanding of 'character', you have a few different Unicode-compliant alternatives for how to access strings, e.g. UTF-8 or 16 or 32 (21-bit Unicode scalars).

 

Fifth interesting thing

Circling back to the first interesting thing: turns out, a flag emoji is always made up of two unicodes (aka "unicode scalars").  At least in Unicode.  In fact, a flag in unicode is a combination of two regional indicators.  For example, Argentina is AR. (Because, I am guessing, that's the two-letter ISO country code; or see here for a pretty table.)  So, going Unicode and using regional indicators instead, 🇦 followed by 🇷 yields 🇦🇷.  (If you paste the two regional indicators into Xcode next to each other, Xcode will automatically convert them into a flag.)  Kind of like e followed by  ́ yields é.

With that in mind, how would you make the following code work?

// Swift 4
let message = "Looking forward to 🇦🇷 vs. 🇯🇵 game!"
let containsFlags = message.contains { $0.isFlag }
let flags = message.filter { $0.isFlag }

For a Swift 4 solution, see the "What's New in Swift" WWDC talk.

 

Technical Links

Fun Links