NEW: Master Swift design patterns with my latest book! >>

What’s new in Swift 4.1

Paul Hudson    January 24th 2018    @twostraws

Apple released the first beta of Xcode 9.3, bringing with it the first release of Swift 4.1 alongside new APIs targeting iOS 11.3. This first point release of Swift 4 brings with it some useful improvements, and if you’re keen to get ahead of the game you can give them a try today.

Start by installing Xcode 9.3 then create a new playground. Let’s take a look at the top three new features for this release…

Synthesized Equatable and Hashable

The Equatable protocol allows Swift to compare one instance of a type against another. When we say 5 == 5, Swift understands what that means because Int conforms to Equatable, which means it implements a function describing what == means for two instances of Int.

Implementing Equatable in our own value types allows them to work like Swift’s strings, arrays, numbers, and more, and it’s usually a good idea to make your structs conform to Equatable just so they fit the concept of value types better.

However, implementing Equatable can be annoying. Consider this code:

struct Person {
    var firstName: String
    var middleName: String
    var age: Int
    var city: String
}

If you have two instances of Person and want to make sure they are identical, you need to compare all four properties, like this:

struct Person: Equatable {
    var firstName: String
    var lastName: String
    var age: Int
    var city: String

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.firstName == rhs.firstName && lhs.lastName == rhs.lastName && lhs.age == rhs.age && lhs.city == rhs.city
    }
}

Even reading that is tiring, never mind writing it.

Fortunately, Swift 4.1 can synthesize conformance for Equatable – it can generate an == method automatically, which will compare all properties in one value with all properties in another, just like above. So, all you have to do now is add Equatable as a protocol for your type, and Swift will do the rest.

Of course, if you want you can implement == yourself. For example, if your type has an id field that identifies it uniquely, you would write == to compare that single value rather than letting Swift do all the extra work.

Swift 4.1 also introduces synthesized support for the Hashable protocol, which means it will generate a hashValue property for conforming types automatically. Hashable was always annoying to implement because you need to return a unique (or at least mostly unique) hash for every object. It’s important, though, because it lets you use your objects as dictionary keys and store them in sets.

Previously we’d need to write code like this:

var hashValue: Int {
    return firstName.hashValue ^ lastName.hashValue &* 16777619
}

For the most part that’s no longer needed in Swift 4.1, although as with Equatable you might still want to write your own method if there’s something specific you need.

Note: You still need to opt in to these protocols by adding a conformance to your type, and using the synthesized code does require that all properties in your type conform to Equatable or Hashable respectively.

For more information, see Swift Evolution proposal SE-0185.

Conditional conformance

Swift Evolution proposal SE-0143 proposed conditional conformances, and it has now been implemented in Swift 4.1. This is a powerful feature that most people will use indirectly – things that didn't work before will now. For example, the following code won’t compile with Swift 4.0:

var left: [String?] = ["Andrew", "Lizzie", "Sophie"]
var right: [String?] = ["Charlotte", "Paul", "John"]
left == right

This is because both String and [String] are equatable, but [String?] was not. Conditional conformance means that it’s now possible to add protocol conformance to a type as long as it satisfies a condition – in this case, if the elements of the array are equatable, that means the whole thing is equatable.

Conditional conformance has been extended to the Codable protocol in a way that will definitely make things safer. Consider this code:

struct Person {
    var name = "Taylor"
}

var people = [Person()]
var encoder = JSONEncoder()
try encoder.encode(people)

That creates an array with a single Person inside, then attempts to encode it to JSON. That code compiles cleanly on Swift 4.0, but throws a fatal error at runtime because Person doesn’t conform to Codable. Swift 4.1 cleans this up: Optional, Array, Dictionary, and Set now only conform to Codable if their contents also conform to Codable, so the above code will refuse to compile.

Conditional conformance is one of those features most people are going to use without realizing, even though they aren’t likely to write much themselves.

flatMap is now (partly) compactMap

The flatMap() method was useful for a variety of things in Swift 4.0, but one was particularly useful: the ability to transform each object in a collection, then remove any items that were nil.

Swift Evolution proposal SE-0187 suggested changing this, and as of Swift 4.1 this flatMap() variant has been renamed to compactMap() to make its meaning clearer.

For example:

let array = ["1", "2", "Fish"]
let numbers = array.compactMap { Int($0) }

That will create an Int array containing the numbers 1 and 2, because "Fish" will fail conversion to Int, return nil, and be ignored.

Looking forward to Swift 5.0

The introduction of conditional conformance has enabled the Swift team to take out a fair amount of code while also promoting stability, and automatic Equatable and Hashable support will definitely make our lives easier.

Other big proposals are currently either in review or in development, including SE-0192: Non-Exhaustive Enums, SE-0194: Derived Collection of Enum Cases, and SE-0195: Dynamic Member Lookup.

But as important as those features are, this is the year Apple will, we hope, deliver ABI stability for Swift, and that’s going to be huge. Fingers crossed!

 

About the author

Paul Hudson is the creator of Hacking with Swift, the most comprehensive series of Swift books in the world. He's also the editor of Swift Developer News, the maintainer of the Swift Knowledge Base, and Mario Kart world champion. OK, so that last part isn't true. If you're curious you can learn more here.

Click here to visit the Hacking with Swift store >>