Swift arrays

This post is part of a Swift vs Objective-C series where we look at new features in Swift and how they compare to their predecesors from Objective-C.
In this article, we are going to discuss Swift arrays and dictionaries.

Make sure to also visit the article about Swift dictionaries.

Whats new with Swift arrays and dictionaries?

I kind of liked NSArray and NSDictionary, to be honest. I thought that they are easy to use and powerful. That’s why I was a little disappointed to learn that Swift changed them so dramatically. Admittedly, collections in Objective-C are more suited to the “power user” – there are really amazing things they can do. But that comes at a price. It can be really easy to lose track of how you’re using them and end up with messy code.

Apple’s engineers re-envisioned Swift arrays by introducing a lot more restrictions and not allowing developers to go crazy with them.

Swift arrays and dicitonaries eliminate primitive obsession

One of the major errors Swift arrays and dictionaries prevent, is Primitive Obsession. Primitive obsession refers to a code smell that involves using primitive data types when you should really have a custom class that holds your data. Many times, in Objective-C this means storing a bundle of related but not homogeneous pieces of information in an array or dictionary. For instance, if you need to store a collection of username and password pairs, you might be tempted to allocate two arrays, one containing usernames and the other passwords, or maybe having an array of dictionaries, each containing a username and password keys. This might be the first thing that comes to mind, but it’s really not a good idea. The right choice would be to create an Account class that contains properties for the information your application requires.

Since Swift arrays can only contain data with the same type (only strings or only numbers, for instance), developers have no choice but to use collections in a way that is easy to understand and maintain.

That being said, I have to say that Swift arrays are a leap forward for the iOS development community. But I’ll probably miss NSArray.

Swift arrays contain objects of the same type

Swift does not allow you to add different types of data in the same collection. When you create it, you have to specify what kind of data you intend to store. Of course, the compiler uses type inference to guess the data type if you omit it. From then on, if you try to add an object from another class to your array, a compile time error will be raised.

Swift arrays mutability

In Objective-C, NSArray is immutable. If you needed to change a collection at runtime, you needed to use it’s counterpart – NSMutableArray. In Swift, there is a more general solution to this problem. And it also works for strings, dictionaries and other primitive data. Mutability is controlled by the variable itself – a var is mutable, whereas a let is immutable.

let myArray:Array<String> = ["Swift", "Array", "Dictionary"]
myArray.append("Collection")

This code generates the following error – “Immutable value of type ‘Array‘ only has mutating members called ‘append'”. Descriptive as always…
However, if we declare myArray as a variable and not a constant, the code will work:

var myArray:Array<String> = ["Swift", "Array", "Dictionary"]
myArray.append("Collection")

After that statement, myArray contains ["Swift", "Array", "Dictionary", "Collection"]

The synthax of Swift arrays

Creating Swift arrays

let myArray:Array<String> = ["Swift", "Array", "Dictionary"]
let myArray = ["Swift", "Array", "Dictionary"]  // type inference allows you to omit the type of the variable 

As you can see, Swift uses the same synthax for array literals that Objective-C introduced in it’s most recent versions.

Accessing and modifying array values

There are many ways to do that and most, if not all, you might remember from Objective-C

let firstElement = myArray[0]
let myArray = ["Swift", "Array", "Dictionary"]  // ["Swift", "Array", "Dictionary"]
myArray.append("Last item") // ["Swift", "Array", "Dictionary", "Last item"]
myArray += ["Last item 2"]  // ["Swift", "Array", "Dictionary", "Last item", "Last item 2"]
myArray.removeLast()        // ["Swift", "Array", "Dictionary", "Last item"]
myArray.removeAtIndex(0)    // ["Array", "Dictionary", "Last item"]
myArray[0] = "First"        // ["First", "Dictionary", "Last item"]

Note: Accessing or modifying an element beyond the array’s bounds will raise an exception:

myArray[13] = "13"    // raises an exception because 13 is beyond the arrays bounds
let element13 = myArray[13] // also raises an exception

Iterating arrays

Iterating Swift arrays is almost the same as in Objective-C:

for string in myArray {
    print(string)
} 

This code will print out every member of the array.

Swift Closures

This post is part of a Swift vs Objective-C series where we look at new features in Swift and how they compare to their predecesors from Objective-C. In this article, we are going to discuss Swift closures.

What are Swift closures?

Depends who’s asking…
To an Objective-C developer, a closure is Swift’s equivilent of blocks.
A formal definition should be that Swift closures are self-contained blocks of functionality
Intuitively, a closure is a kind of anonymous, nested functions. It’s a chunk of functionality that you can pass around in functions and variables.

In reality, closures and blocks do little more than provide a more convinient way of encapsulating functionality than nested fuctions and function pointers. Despite that, in the past couple of years, there has been a massive effort to integrate blocks into our Objective-C code.

Swift closures synthax

Swift closures closely resemble Objective-C (or any other language, supporting them) blocks. To define one, you’d write something like this:

{ (parameters) -> return_type in
    // block body
    // write code here
}

This is longest, most formal way of creating Swift closures. As with all languages influenced by functional programming, there are many shorter versions, which we will cover shortly.

Closures as function parameters

Let’s face it, you are most likely to use Swift closures as parameters. Let’s take a look at some specifics to doing that.
First of all, it is important to know how to define a function that takes swift closures as one of it’s parameters:

func calculateSomething(something1:Float, something2:Float, calculator:(value1:Float, value2:Float) ->Float) ->Float {
    return calculator(value1: something1, value2: something2)
}

I hope there is nothing disturbing in this statement to you. It’s a function that takes three parameters – two floating point numbers and another one called calculator. When we inspect it’s type, we will discover that it’s not a basic data type or a class. It’s a function signature, specifying what parameters the closure takes and what value it returns.

Now, to use the calculateSomething function, we can do the following:

calculateSomething(23.76, 125, {(value1:Float, value2:Float)->Float in 
    return value1 + value2
})

Written like this, the function is calculating sums. As you can see, we supplied two numbers and a closure that is essentially a very complicated + operator. However, as with most “functional” languages, that is simply too long to write. Life is too short to write swift closures with the full synthax. That’s why there are shorter versions of this statement.

calculateSomething(23.76, 125, {(value1:Float, value2:Float) in 
    return value1 + value2
})

Type inference to the rescue! Since the compiler already knows the signature needed for this function call, it can “guess” what a suitable closure would look like. That’s why we can skip explicitly specifying it’s return type. You might wonder if the same is true about the parameter’s type. Well, it is…

calculateSomething(23.76, 125, {(value1, value2) in 
    return value1 + value2
})

All data types can be inferred from the function definition.
While we are at it, we can also omit the parenthesis:

calculateSomething(23.76, 125, {value1, value2 in 
    return value1 + value2
})

Next, we can continue with the closure’s body. In swift, you can omit the return keyword for functions that have only one statement. Since this is the case in our example, we can shorten our code even more:

calculateSomething(23.76, 125, {value1, value2 in 
    value1 + value2
})

But wait, there’s more! Here’s an interesting little feature from scripting languages. You might know (from Bash for instance) that you can access function and script paramenters using the $ synthax (like $0, $5, $8). So…

calculateSomething(23.76, 125, {
    $0 + $1
})

Note that inlike Bash, where $0 is the path to the script being executed, in Swift it is actually the first parameter.

Pretty nice, eh? Our function call got a lot shorter. Of cource, this is just synthax sugar. It doesn’t add any expressive power to swift closures – it just makes them more convenient to write and read.

As a bonus for being so patient, here’s one final short form. Since the closure we were using sums two numbers, which is exactly what + does… we might as well use that operator:

calculateSomething(5.0, 12.6, +)

Yes, that’s a thing in Swift.

Variables of type closure

Sometimes, it can prove useful to store swift closures in a variable. So, let’s briefly talk about that.

let closureVar = {(value1:Float, value2:Float)->Float in 
    return value1 + value2
}

By now, you should be comfortable with this synthax. It’s not much different than what we looked at above. Though, it looks like a long this to write. It almost makes you not want to use that variable. Can’t we use something shorter, like we did last time?

let closureVar2 = {(value1, value2) in 
    return value1 + value2
}

It doesn’t work ;(. Why? Well, we can omit the parameter data types and return value only if the compiler can infer them from the context. And since we didn’t specify the closureVar2‘s type, Swift doesn’t know the closure’s signature that it should expect.

let closureVar3:(value1:Float, value2:Float) ->Float = {(value1, value2) in 
    return value1 + value2
}

Explicitly adding a type to our variable solves that problem, but our statement is no longer that short.

Now that we have a variable containing our closure, we can use it in all situations a closure is needed. Like in all examples from the previous paragraph:

calculateSomething(5.0, 12.6, closureVar)

Capturing values

This section contains some general information about capturing values. If you are familiar this concept from Objective-C’s blocks, feel free to skip the following paragraph.

Everything up until now is not that impressive to be honest. Being able to store functions in a variable and use them as parameters is a standard feature of most languages. What makes Swift closures (also blocks and lambda functions in Objective-C and other languages) so popular, is capturing values. The concept is rather simple. Unlike conventional function that operate in a sort of a vaccum, closures have the ability to use variables defined in the code block enclosing them. Let look at an example:

func myFunction() {
    var funcVariable = 15
    let closureVar: () = {() -> () in
        // This closure will be able to access variables 
        // from the function it was defined from -
        // funcVariable for instance
        var closureVariable = funcVariable
        funcVariable = 25
        }()
    closureVar
    print(funcVariable)
    // funcVariable is now 25
}

The outer function myFunction creates a local variable funcVariable. After that it defines a closure, which is able to use that local variable and even change it. Actually it has a reference to it so that if the value is modified within the closure, the new value doesn’t get lost as soon as the code block ends.

Retain cycles with Swift closures

Capturing values is a pretty useful feature. However, there are some things to be careful with. As the title suggests, they are related to retain cycles. Since the closure has to make sure all local variables that it needs from it’s container are readily available within it’s body, it retains them. It is possible that an object retains a closure, and that same object is used within the closure’s body, meaning that they both keep each other “alive”. Most often this happens when a class has a closure as a member variable and that same closure uses self within it’s body. In such cases, the object retains the closure, which in turn retains the object of the class.

Retain cycles like these are relatively hard to track because they are very subtle. And with ARC, things are getting even worse as most developers lose the habbit of thinking about memory management.

Enumerations in Swift

This post is part of a Swift vs Objective-C series where we look at new features in Swift and how they compare to their predecesors from Objective-C.
In this article, we are going to discuss enumerations in Swift.

What’s new with enumerations in Swift

Another day, another programming language…
With the addition of Swift as a development platform for writing Mac and iOS apps, it is time to think about translating our knowledge of Objective-C to Swift. Enumerations are a perfect place to revisit as Swift contains a lot of improvements and new features as opposed to it’s predecessor.

For the most part, you can use enumerations in Swift in the same way you did previously in Objective-C… or C/C++ for that matter. There are some minor syntax changes, but other than that the mechanics are the same.

Let’s look at an example. Let’s say we are developing a reader application that displays different types of books – PDFs, EPUBs, web pages etc. We need a variable that determines which type of media we are currently showing to the user.

In Objective-C we would create an enum similar to this:

enum eBookType
{
    eBookTypePdf,
    eBookTypeEpub,
    eBookTypeWebPage,
    eBookTypeMsWord,
};

Now if we want to translate this to enumerations in Swift, we’d write something like:

enum BookType {
    case Pdf
    case Epub
    case WebPage
    case MsWord
}

As you can see, there are a few changes.
First of all, each entry is prefixed with the case keyword. It tells the compiler that a new line of member definitions starts. But you can also put several definitions on a single line:

enum BookType {
    case Pdf, Epub, WebPage, MsWord
}

You might have noticed that the naming convention has changed from the Objective-C to the Swift example. Though most things are not covered by the language’s specification and are largely subjective depending on your coding style, I’ll try to explain my motivation for the choice of names.

  • Enumeration name

    Since enumerations in Swift are more similar to classes and structures than their C counterparts, their names should resemble class names. That’s why the BookType name starts with a capital letter. Even though this is not mandatory, it is mentioned in Apple’s book as the recommended style.

  • Member names

    I like to put the enum name as the begining of the member. That’s how I always know which data type it belongs to. However, enumerations in Swift use the dot notation to access members. So, to use the Pdf member, you would write BookType.Pdf. In such case, it doesn’t make sense to use the naming convention from the Objective-C example. Otherwise, the finished statement looks awkward: BookType.BookTypePdf.

New features

So far, enumerations in Swift do not look that different. However, we have only scratched the surface. While, they support all the functionality from C enums (with little modification), enumerations in Swift also introduce a number of new concepts. Here they are:

Dot notation

I already mentioned this above, but let’s repeat it nevertheless. Similar to structures, enumerations in Swift use the dot notation in order to specify a member:

enumeration_name.member_name

This makes statements more explicit about the enumeration they are refering to. It may not seem that important, but I feel that this is a real upgrade from the way C enums work. Unless you enforce a naming convention that helps you link members to their respective enumerations, it might become difficult to know which data type a member belongs to.

Enumeration member values

In C, each enum member is assigned an integer number. Getting back to our previous example, the members of eBookType have the following values:

  • eBookTypePdf – 0
  • eBookTypeEpub – 1
  • eBookTypeWebPage – 2
  • eBookTypeMsWord – 3

Whenever you refer to eBookTypePdf, for instance, it is the same as using 0.
This does not apply to enumarations in Swift. Instead, each Swift enum member has a fully-fledged value that could be either a string, a character or a number. This allows you to “attach” additional information to an enumeration member. This additional information is called an associated value

Associated values

Associated values allow you to add a string, character or number variable to an enumeration member. Let’s illustrate this with an example. Using the enum from the previous paragraph

enum BookType {
    case Pdf
    case Epub
    case WebPage
    case MsWord
}

we would also want to link each book with it’s title. The Epub member specifies that the current book is in Epub file format and it’s associated value indicates it’s name. So, when writing a view controller displaying the book, the following statement might prove useful:

viewController.book = BookType.Epub("Bedtime stories")

Naturally, in order to support this string value, we need to update our enum definition:

enum BookType {
    case Pdf(String)
    case Epub(String)
    case WebPage(String, NSURL)
    case MsWord(String)
}

Notice how WebPage has two associated values. Enumerations in Swift are not limited to a single associated value.

Switch statements using enumerations in Swift

Using enums in switch statements is not very different from before, but there are several things to note.
First of all, you have to provide a case for all members. If you don’t want to do that, you need to add a default case to handle all unspecified members:

let book = BookType.MsWord
switch book {
case .Pdf:
    println("This is a PDF")
case .MsWord:
    println("This is a Word file")
default:
    println("Either an EPUB or a web page")
}

In this switch, we are only explicitly handling the PDF and MSWord cases. Since Web page and EPUB are not, we had to provide a default case for them. If we didn’t, the compiler would have returned an error.

You can also integrate associated values into your switch statement:

let book = BookType.MsWord("Enumerations in Swift for dummies")
switch book {
case .Pdf(let bookTitle):
    println("This is a PDF: \(bookTitle)")
case .MsWord(let bookTitle):
    println("This is a Word file: \(bookTitle)")
default:
    println("Either an EPUB or a web page")

}

Raw values

Raw values are similar to the integer values enum members have in C/C++. They are the default values a member of enumerations in Swift has. It always has the same data type across all members and like associated values can be either a string, a number or a character.

Here’s how we can assign numbers to the values in our BookType enumeration:

enum BookType: Int {
    case Pdf = 0
    case Epub = 1
    case WebPage = 2
    case MsWord = 3
}

Integer raw values do auto-increment if not explicitly specified, but you cannot assign the same raw value twice within a single enumeration in Swift.

You can always access an enum member’s raw value via the toRaw method. The opposite is also possble using the fromRaw function:

let rawPdf = BookType.Pdf.toRaw()
let book = BookType.fromRaw(3)      // MsWord

In this example the book variable is of type optional BookType (BookType?), because it might return nil if you provide a raw value that does not exist.

Swift initializers – designated and convenience

This post is part of a Swift vs Objective-C series where we look at new features in Swift and how they compare to their predecesors from Objective-C.
In this article, we are going to discuss designated and convenience Swift initializers and their Objective-C counterparts.

Designated and convenience initializers

You should already know that Objective-C has things called designated initializers. It’s not something you absolutely MUST know, but it can often help you write better class interfaces.
The concept is simple – a designated initializer is guaranteed to be called during object creation. Even if you explicitly use another init method, the class “promises” to call a designated one sooner or later (a class can have more than one designated initializers and Objective-C does not specify which one should be used – it assumes all of them can fully initialize an instance). That way, you can be certain that the code in it is always going to execute no matter which constructor you use.

A convenience initializer is every initializer that is not designated. You can use them to give the clients of your class different options when it comes to creating objects. For instance, a UIViewController can be created:

  • without any parameters
  • using NSCoding (initWithCoder:)
  • with a Nib name

Among these options, the last one (initWithNibName:bundle:) is the (only) designated initializer. It is quaranteed to be called during initialization.

Note: All Cocoa classes have a designated initializer and respect the initializer chain.

Some considerations should be taken into account with subclassing regarding the initialization chain. Basically, in addition to having a designated init method yourself, you have to make sure that it calls the corresponding designated method in it’s superclass. This ensures that all classes in the inheritance tree have a chance to fully prepare the new instance and not leave any if it’s variables in an undefined state.

This might not sound too important for you right now, but not respecting the designated initializer chain can lead to subtle bugs. I strongly recommend that you read the following article about Objective C Initializer Patterns in Twitter’s blog

Swift initializers vs. Objective-C init

The problem with designated initializers in Objective-C is that most developers ignore them. Unfortunately, this trend will probably continue with Swift initializers as well. You can program all your life without ever thinking about designated and secondary init methods. However, Swift initializers are a little more explicit as to what type an init method is.
Every method that you write with the following synthax:

init (/* arguments */)

is a designated initializer. It implicitely becomes one. There is not special keyword to mark it as such. This is not true for convenience initializers. Here’s an example:

convenience init (/* arguments */)

By including the convenience keyword, we explicitely specified that this is a convenience initializer.

Convenience Swift initializers are subject to the following restrictions:

  • They must always call a designated initializer within their body.
  • A class must have at least one designated initializer, though it is possible for it to be inherited from a superclass.

The following example showcases the main use cases for convenience Swift initializers:

class BaseClass {
    var someVar: String

    // a designated initializer
    init () {
        someVar = "test"
    }

    // another designated initalizer
    init (someValue: String) {
        someVar = someValue
    }

    // a convenience initializer
    convenience init(someInt: Int) {
        // must call self.init
        self.init(someValue: "Hello")
    }
}

// FirstSubclass does not have a designated initializer
// It inherits it from Base Class

class FirstSubclass : BaseClass {

    convenience init(unsedVar: AnyObject) {
        self.init(someValue: "First")
    }
}

// SecondSubclass does not have a superclass with a designated initializer
// thus the following code with raise a compilation error - you cannot have
// a class without a designated initializer

class SecondSubclass {
    convenience init(unsedVar: AnyObject) {

    }
}

// Raises a "Super.init isn't called before returning from initializer" compilation
// error. When subclassing, all designated initializers must call one of the base
// class's designated init methods

class ThirdSubclass : BaseClass {
    var data: NSData

    init(someData: NSData) {
        data = someData
    }
}

Overall, Swift initializers are a little more… pretentious when it comes to the initializing chain. While still keeping out of the way and working seamlessly with code that does not define designated and convenience init methods, it keeps reminding you to think about the initialization process. Hopefully, it will motivate us to write better class interfaces.

Don’t hasitate you share your thoughts about designated and convenience Swift initializers in the comment section.
Thanks for reading!

Swift optional values

This post is part of a Swift vs Objective-C series where we look at new features in Swift and how they compare to their predecesors from Objective-C.

What are Swift optional values?

Optional values are a major weapon in Swift’s arcenal. It’s unlike anything I’ve seen in my professional carrier as a developer, though I’ve read that there are languages with similar concepts. They are designed as a replacement to Objective-C’s way of treating nil references.

Swift makes heavy use of optional values. They are absolutely everywhere. So you better get used to them. The bad news is that they take a little bit of time and practice to get right. In fact, I still have problems with them at times.

Objective-C message dispatch

Let me step back a little bit. Even the most inexperienced iOS developer has noticed that Objective-C deals with pointers to nil differently than Java for instance. For one thing, it doesn’t make the application throw an exception. But why is that? And how?

The second question has a lot to do with the way Objective-C dispatches method calls to it’s objects. In short, it reads the object that the reference is pointing to, and asks it which class it is a member of. Having that information, it finds the code for the right method, based to that class and if everything goes well, calls it. This mechanism is not too strict when it comes to nil pointers. When you try to dispatch a method call using such a pointer, instead of treating it was an exceptional behavior, it fails gracefully by ignoring the invokation.

One might argue that allowing that kind of behavior might result in obscure bugs, just because your methods calls might not actually work. Isn’t it better to just crash and have the developer rethink his code? Well, not necessarilly. Nil pointers DO exist and they are not always signs of incorrect bahavior. Sometimes, a function has nothing to return and it has no choice but providing nil. Does this mean, the application cannot recover? Not at all. If it crashes when you try using a pointer like that, you code will soon be filled with pointless if statements that do nothing but confuse people reading it.

By allowing messages to be dispatched to nil objects, Objective-C code has much less security checks and is, therefore, much easier to read.

Where Objective-C falls short

The previous paragraph has probably made you think that Objective-C is already good enough at handling nil references. However, there are a few exceptions.

First of all, it only works for objects. Values, such as integers, enums and structures are not subject to the same message dispatch mechanism and, hence, don’t behave that way. That means that you have to be aware what type of data you are working with.

Secondly, Objective-C’s synthax does not provide any hint about the validity of returned data. You can never be sure if a method returns nil because an error has occured, or there was simply no data there to supply. You have to rely on your documentation (if you have any) or method name to let others know what it means for that method to return nil.

Nil 2.0 – Swift optional values

As already mentioned, Swift optional values are everywhere. I doubt there was more than a few classes that don’t have them. They are the language’s way of indicating that a variable does not have a value. Normally, a variable or constant points to a piece of data in memory. This is often referred to as binding. A variable is bound to an object. However, what happens when you have a variable, but you don’t have an object to associate it with. A common example of this scenario is a function that has a return type, but given it’s input, there is no data to actually provide. It still has to return something, so a common solution is to get a reference that points to an invalid address or a value that is not acceptable in the context. In Objective-C, methods return nil for objects and special constants like NSNotFound for primitive data types.

Swift handles this situation by the defining the term no value. Swift optional values tell the developer “This variable might have some kind of value, or no value at all”. The “No value” is universally accepted across classes – “No value” for String variables is the same as “No value” for integers or view controllers. That’s how Swift developers have a clear definition of what it means for a variable to not have a valid value.

Swift optional values synthax

Let’s compare a normal variable to a swift optional value definition.

var myVariable: String

This is a standard string variable. And this:

var myOptionalVariable: String?

is an optional string variable. The difference is the question mark at the end. It had to follow the data type. This definition creates the myOptionalVariable variable and associates it with “No value”. Note that “No value” is different than nil in Objective, where it is just a pointer that refers to an invalid location.

You can explicitely specify that you want a variable to have no value by writing:

myOptionalVariable = nil

Accessing Swift optional values

Swift really wants you be aware when you’re using optional values – that’s why it wants you to be very explicit every time you use them. It wants to contantly remind you that you are working with a variable that may not have a value. There are several ways to access an optional. The first one we are going to discuss is forced unwrapping.

Forced unwrapping

This is the easiest way to access Swift optional values. But it’s also the most “dangerous”. It is important to note that using an optional that has no value will cause an exception to be thrown in runtime. So forced unwrapping just instructs the program to get the value without any additional checks. You have to be absolutely certain that there is a value in the variable, otherwise you risk a crash. The following synthax:

 myOptionalVariable!

is how you unwrap your optional.

Optional binding

Optional binding is the safest way to unwrap an optional. Consider the following code:

if let nonOptional = myOptionalVariable {
    // use nonOptional safely
}

Here a new variable (nonOptional) is created to hold the unwrapped value of myOptionalVariable. It is not an optional so it is safe to use it within the if statement’s body. If myOptionalVariable has no value, the code inside the if statement will not be executed.

Implicitly unwrapped optionals

Like many other features in the language, Swift optional values acknowledge common use cases and provide shorter ways to write them. Often, you will have an optional, but right from the start you will be fairly certain that it DOES in fact contain a value. So instead of using forced unwrapping everytime you use them, you can define those variables as implicitly unwrapped optionals like so:

var myImplicitOptional: String!

This new variable is an optional in every way, but it differs in the way it’s accessed. You don’t have to forcefully unwrap it everytime you use it. Just write it’s name without the exclamation mark. It’s still going to raise an exception if there happens to be no value in it, but it spares you the hassle of unwrapping every time (developers are lazy).

Optional chaining

The Swift programming language defines optional chaining as:

“Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil”

Intuitively, optional chaining allows you to call methods and access properties that don’t necessarily have a value. Like you would expect from Objective-C, if an optional in a chain has no value, the whole expression evaluates to nil.

To back these explainations with an example, optional chaining looks something like this:

nonOptional.optionalProperty?.someMethod()

Note that you can achieve the same call (sort of) by simply typing:

nonOptional.optionalProperty!.someMethod()

The problem, however, is that if optionalProperty happens to be nil, an exception will be thrown. Optional chaining on the other hand fails gracefully by not calling someMethod and returning nil as a result. In fact, all subsequent method calls winthin the same statement will not be called.

As you already saw from the example, optional chaining’s synthax differs by replacing the exclamation mark with a question mark. That’s what instructs Swift to use chainging instead of forced unwrapping.

Conclusion

In conclusion, I’d like to say that Swift optional values are a must have for all iOS developers trying to switch from Objective-C. They are literary everywhere in the API. There is hardly a single class that does not have them. Also, they can take a little time to get used to. That’s why it is important to pay them the attention they deserve.

Thanks for reading!