Yassine Houssni Yassine Houssni - 6 months ago 7
Swift Question

What is the difference between String? and String! (Two ways of creating an optional variable)?

In The Swift Programming Language (book of Apple) I've read that you can create optional variables in 2 ways: using a question mark (?) or by using an excamation mark (!).

The difference is that when you get the value of an optional with (?) you have to use an exclamation mark everytime you want the value:

var str: String? = "Question mark?"
println(str!) // Exclamation mark needed
str = nil


While with an (!) you can get it without a suffix:

var str: String! = "Exclamation mark!"
println(str) // No suffix needed
str = nil


What is the difference and why are there 2 ways if there is no difference at all?

Answer

The real benefit to using implicitly unwrapped optionals (declared with the !) is related to class initialisation when two classes point to each other and you need to avoid a strong-reference cycle. For example:

Class A <-> Class B

Class A's init routine needs to create (and own) class B, and B needs a weak reference back to A:

class A {
    let instanceOfB: B!
    init() {
        self.instanceOfB = B(instanceOfA: self)
    }
}

class B {
    unowned let instanceOfA: A
    init(instanceOfA: A) {
        self.instanceOfA = instanceOfA
    }
}

Now,

  • Class B needs a reference to class A to be initialised.
  • Class A can only pass self to class B's initialiser once it's fully initialised.
  • For Class A to be considered as initialised before Class B is created, the property instanceOfB must therefore be optional.

However, once A's been created it would be annoying to have to access instanceOfB using instanceOfB! since we know that there has to be a B

To avoid this, instanceOfB is declared as an implicity unwrapped optional (instanceOfB!), and we can access it using just instanceOfB. (Furthermore, I suspect that the compiler can optimise the access differently too).

An example of this is given on pages 464 to 466 of the book.

Summary:

  • Use ? if the value can become nil in the future, so that you test for this.
  • Use ! if it really shouldn't become nil in the future, but it needs to be nil initially.
Comments