What's New in Swift 4, An Opinionated Review - Digital Leaves
2697
post-template-default,single,single-post,postid-2697,single-format-standard,qode-social-login-1.0,qode-restaurant-1.0,ajax_fade,page_not_loaded,,select-theme-ver-4.1,wpb-js-composer js-comp-ver-5.2,vc_responsive
What's New In Swift 4

What’s New in Swift 4, An Opinionated Review

Finally! After the WWDC, we have a new Xcode 9 (in beta) and a new “official” release of Swift, Swift 4. Even though we already knew the proposals that were going to be introduced in the language beforehand, now that those proposals have been accepted and presented at the WWDC, it’s the perfect opportunity to see what’s new in Swift 4.

Warning: this post contains a very opinionated view of what’s new in Swift 4. Of course, this is just my personal, subjective opinion. If yours is different, let’s discuss that in the comments 🙂.

What’s new in Swift 4

Contrary to most programming languages, Swift has been a language in continuous evolution since it was released back in 2014. This process took a whole new magnitude when it was open sourced one year later.

While I was certainly excited when this evolution process started, that excitement has dwindled.

Migrating Your Projects To A New Swift Version

First and foremost, migrations have always been a nightmare. There’s a migration tool, but it’s far from perfect. I have about 20+ projects written in Swift that I need to update with every new release of Swift.

Usually, it takes me around 2 weeks to migrate them all. This is time wasted, because during that period I cannot work on any of them.

Furthermore, I always find problems in the process. Sometimes I have had to spend days with absolutely weird errors (like compiler crashes), and trust me, that’s no fun.

Secondly, and most importantly, I’ve got the feeling that Swift engineers and open source volunteers are trying to cure human stupidity.

I will expand on this as we discuss the changes. However, I think they need to relax and admit that no language, no matter how safe and fast it is, is perfect. They need to acknowledge that the responsibility of the developer is producing great code, and the responsibility of the language is making the life of the developer easier, not the other way around.

The responsibility of the developer should be producing great code, and the responsibility of the language making the life of the developer easier, not the other way around.

That said, let’s have a look at what’s new in Swift 4 then, and also in our favorite IDE: Xcode.

If you have been following the different proposals for Swift 4 during its development, you already know most of this stuff.

However, if that’s not the case, here’s a summary of the most important changes.

Refactoring

Imagine that you have a class with a method you are using in several parts of your code. Suddenly, you realized that the name doesn’t really reflect the purpose of the method. Then, willing to make you code as legible and maintainable as possible, you decide to rename that method to something more appropriate.

However, then you will have to rename all calls to that method everywhere in your project.

That’s why Xcode introduced refactoring, that allowed you to perform this, and many other corrections and changes automatically.

Nevertheless, refactoring had never been available for Swift, only for Objective-C. Until now.

This is a huge advantage, I’ve been waiting for this feature for years now. Furthermore, now we have the ability to add our own refactorings, customizing how to automate changes all over our projects.

Package Manager

The Swift Package Manager has been around as a more or less developed concept since Swift 3. However, apparently with Swift 4 and the new Xcode, its going to be deeply integrated in the IDE.

Right now, there are more than 7000 packages available in Github, and the number keeps on growing. Important to notice is the large number of great packages for Server-Side Swift.

All in all, the Package Manager is not as mature as, say, npm, but it’s certainly improving fast.

I plan on devote a whole post to the Package Manager and how to use it, so stay tuned!

Access Control

There’s a slight change in the way that properties can be accessed for classes and structs.

Previously, if you had a private variable or method in a class, it could only be accessed by methods and properties defined at that very same class definition. Thus, no extension, even declared in the same file, could access that variable.

That was kind of annoying, so a common trick was changing the variable from private to fileprivate.

However, new in Swift 4, variables can be declared private and still be accessed by extensions defined in the same file.

Composing Classes And Protocols

This is a huge improvement in my humble opinion. Swift 4 adds the ability to define a type declaration as a combination of several types, classes and protocols, together.

Let me illustrate how it works with an example.

Playful Animals

First, imagine that we have an Animal class.

Next, imagine also that we have a protocol called Playful, that determines if an object is playful or not by calling its isPlayful() method.

Then we can define two subclasses of Animal that implement this, Dog (which are always playful) and Cat.

In Swift 3, if we wanted to iterate through a list of animals that happen to implement Playful (like Dog and Cat), we could declare them as either animals or playful entities, but not both.

Multiple Type Definition In Swift 4

However, in Swift 4, we can declare an array of “animals that are playful” and iterate through them.

Even though this is just a simple example, I think this feature is going to be really helpful. Good one here, Apple.

Source Compatibility

According to Apple, Swift 4 is largely going to be compatible with Swift 3. However, I tend to be wary of such bold statements. They proclaimed the same exact thing when Swift 3 was released, and turned out not to be that accurate.

It’s worth mentioning that there’s now a in-the-middle version, Swift 3.2. The goal of this version is allowing you to use the Swift 4 compiler while still using the Swift 3 syntax, helping in the adaptation.

I have yet to start migrating my projects to Swift 4. Nevertheless, the fact that Strings have changed again -I talk about that below- means that probably a lot of work is going to be devoted to the migration process.

Well, we still have the automatic migration tool, and it works like magic, right?… RIGHT?

Improvement in Builds and Compiling Time

Under this section, I will briefly enumerate many improvements that supposedly make the compiling and building process faster.

To be honest, I think it’s quite nice that Apple engineers and volunteers keep on pushing forward to make the compiler faster and the building process better in general. However, sometimes I feel like these kind of improvements are like when Tim Cook’s on stage to present a new iPad that is “7% thinner” than its predecessor, with a “5,5% improvement in battery life”… those are certainly nice improvements, but overall, I would rather have them fix the annoying SourceKit crash bug that has plagued Xcode for years now, or offer a real solution for the indexing problem.

Anyway, to be honest, the list of improvements and enhancements is quite impressing, so let me enumerate the more interesting ones to you:

Improvements In The Build System

The building process system has been completely tweaked to make it faster.

Pre-Compiled Bridging Headers

Previously, bridging headers were re-compiled every time you made a change in a Swift file. This is important because they take a lot of time to process and compile. Not anymore. Now, they are pre-compiled.

Some Optimizations When Indexing

Even though the indexing problem has not been addressed specifically, there’s a nice addition. Whenever you build your project, Xcode performs a complete indexing. Thus, it doesn’t make sense keep on indexing in the background once you have built your product.

Reduced Code Size

Amongst the different improvements introduced to reduce the size of the binaries, Apple presented one that seems very clever to me. In summary, it analyzes which parts of the code are not accessed in your program, and don’t include them in the compilation. For example, think of a library you are using where you only really access a handful of methods or properties. Why would you need to link the whole library?

Of course, this can be applied to your code, extensions and libraries too.

Dropping Objective-C Support Unless Explicitly Specified

I’m not sure I really like this “improvement”. It will surely give me -and probably a lot of other developers out there- some headaches.

By default, Swift functions, methods and properties will not generate its Objective-C compiled counterparts. This means that you won’t be able to call a method from Objective-C that belongs to a Swift class.

For now, these accesses will appear as warnings in the console when you run the code, something among these lines:

In order to fix this, you will have to add an explicit @objc tag to any methods, functions, or properties being accessed by Objective-C code.

I’m worried that these console warnings will not be enough to allow us locate all the single points when we are accessing Swift code from Objective-C. As a result, it could cause some of our projects to crash for our users.

Furthermore, I certainly have a lot of projects to maintain that started as Objective-C projects and still contain a good amount of Objective-C code. Oftentimes, this code access Swift functions. I’m not sure I’m in the mood for adding all those explicit @obc declarations manually.

I will bring you up to date as soon as I start migrating my projects.

Strings

Some time ago, I wrote about the changes that might be introduced for Strings in Swift 4. As it turns out, most of those changes have been finally included.

Bye, Bye, string.characters

First and foremost, String is again a collection of characters on itself. It lost this condition in Swift 2, where the rather ugly string.characters was introduced.

This is, in my opinion, a very welcomed change. No more string.characters.count.

The Attack Of The Evil Substrings

However, not everything is good news. One of my biggest fears was the proposal for a new type called Substring, that will be the result of operations that might divide a string in parts or fragments, such as split:

This is a huge, huge mistake in my humble opinion.

Not only makes your code clumsier and harder to read -I can see myself adding castings and initializing Strings with Substrings-, but it’s completely counter-intuitive.

Would you say that a part of an array of Int is an array of SubInts?

Of Strings, Characters and Graphemes

I think the main problem is that Apple engineers still try so hard to see a String as a collection of characters.

This is the classical “model VS reality” issue. Strings can no longer be seen as mere collections of characters. Not since unicode.

To elaborate on this, let me use an example from the very talk in the WWDC 2017 Video of “What’s new in Swift”.

As you probably know, a character in Swift is not a single “character” (in the old C sense of the word), but a grapheme.

Thus, a grapheme can be the result of combining together multiple symbols. “é” is equivalent to “e”+”´”.

If a String was a collection, when you add elements to it, the number of elements of the collection will certainly increase.

However, that’s not true for Strings, as this example from the WWDC shows:

As you can see, we added three elements, but the total count of characters (read: graphemes) is one.

A String Is Not A Collection

As soon as they realize that a String is not the same as an array of Ints, I hope they will stop messing around with Strings. Indeed, Strings in Swift have been punished and messed around with on every Swift release to date.

And that’s another problem too. The API of Strings in Swift has been subject to change every single year since Swift 1.0. That takes a huge toll when maintaining your projects.

We, developers, don’t really need to philosophize on the nature of Strings. We need to be able to use them easily and comfortably in our code, employing as less artifacts as possible.

So all in all, while I’m glad that string.characters has disappeared, I’m not happy at all with this Substring thing. Oh well, probably that will change for Swift 5, so…

Some Other Changes

Additionally, there are some minor changes that are nice, if not specially useful, at least for me.

First, they introduced a “…” symbol that indicates a range of iteration from a given String index to the end of the String.

Also, there’s a new triple quote syntax to write Strings with multiple lines directly:

Not that those are not cool or anything, but I would rather get an easy way of accessing indexes with integers like most languages do.

Generics And Sequences

There are some minor changes in Generics and Sequences. Not really mind-blowing stuff, but worth talking about the most important changes.

First, in Sequence, you no longer need to use Iterator.Element for extensions. You can just use Element. This is thanks to the addition of “Associated types”:

Just be careful to check that these new associated types don’t conflict with already defined constraints for Sequence or Collection you may have defined.

Next, we now have new methods available that allow us to perform direct modifications on sequences, such as:

MutableCollection.swapAt(_:_:)

This method allows us to exchange two elements in a sequence directly. Without getting a lot into the technical stuff, these new methods are possible thanks to changes in how the sequence elements are accessed and indexed.

Ownership And The SE-0176 Proposal

Under this umbrella, there are some changes to how our code can access fragments of information, data and variables.

The goal of these changes is preventing you from accessing a piece of memory, say, an array in a block, where you iterate through it, and call a function inside that will modify it, effectively affecting the iteration process and probably causing a crash or a bug.

As an example, imagine that you have an extension to MutableCollection to allow you to perform a mutable operation on every element of the collection, such as:

Then, nothing prevents you from misusing this method to perform dangerous operations such as:

Certainly, the numbers.removeLast() call will mess up with the collection during the iteration process and provoke an exception or crash.

Apparently, now the compiler is going to prevent you from performing these kinds of operations. Thus, they will be enforcing ownership and exclusive access between read-write operations.

Why I Don’t Like This Idea

While this may seem nice in theory, the more I think about it, the more I dislike the idea.

I wonder how many of my operations will be marked as “potentially dangerous”, and the “exclusive access” policy will prevent me from doing what I want to do.

My point is, I am certainly aware of what my code does. So should you.

If I ever write code like the one depicted above, I deserve my application to crash.

I was banging my head against the wall wondering why all these changes, and then suddenly it all became clear.

 

Swift Needs To Be Safe…

Overall, I couldn’t express my feelings about the evolution of the Swift language until I heard this guy in the WWDC video expressing them with words:

Swift needs to be safe

And then it all made sense like pieces of a puzzle falling into their right places. The drifting String API changes, the Ownership stuff, the enforcement of type safety up to ridiculous levels…

I think they are trying to cure human stupidity with Swift.

And they can’t. They shouldn’t either.

Developers need to know what they are doing. Furthermore, they need to be aware of what their code means, how it works and the results it generates.

We need to make mistakes and understand why we shouldn’t modify the same piece of information in two different threads at the same time in a non-safe way. We need to understand that, if a variable can possibly return nil, we need to check its value when we are handling it.

What Does The Future Hold For Swift

Please, take a moment to consider this instruction:

Is it really type safety helping here? Or does this desperate attempt to prevent human stupidity actually prevents Swift from being the elegant, simple and minimalist language it once was should be?

Consider this other instruction, that was perfectly fine in Swift 2:

Now, we need to do this, effectively ruining Swift elegance and simplicity, and making optional chaining useless:

Or even worse:

With each iteration, I am getting less and less excited about the Swift language. I really dig for the simplicity and flexibility of the initial versions of the language.

Nevertheless, I still love developing for the Apple ecosystem, and Swift is a great language… but every year, the changes are getting more and more annoying for me, and updating my projects is becoming quite “the month” with every release of Swift.

What’s new in Swift, you ask? I wonder what’s next…

In Summary

In this article, I gave you a probably very opinionated review of what’s new in Swift 4 🙂.

Now that the WWDC is over, we have a short period to get used to the changes, and migrate our projects.  As I stated before, migrating my projects to new Swift versions have always been a nightmare. I really hope this time it’s going to be easier. I will bring you up to date in a future post.

What are your thoughts on the new Swift release? Did I miss something? Please, let us know in the comments.

 

No Comments

Post a Comment

Before you continue...

Hi there! I created the Digital Tips List, the newsletter for Swift and iOS developers, to share my knowledge with you.


It features exclusive weekly tutorials on Swift and iOS development, Swift code snippets and the Digital Tip of the week.


Besides, If you join the list you'll receive the eBook: "Your First iOS App", that will teach you how to build your first iOS App in less than an hour with no prior Swift or iOS knowledge.

I hate spam, and I promise I'll keep your email address safe.