0

I know the concept of optionals and forced unwrapping but just to quote an example from iOS 8 Swift Programming Cookbook, I don't understand why var imageView: UIImageView is used in example 1 but forced unwrapping var imageView: UIImageView! in example 2. Hopefully, someone tells me what I am missing here so I know what to read up on.

Example 1:

class ViewController: UIViewController {
    let image = UIImage(named: "Safari")
    var imageView: UIImageView

    required init(coder aDecoder: NSCoder) {
        imageView = UIImageView(image: image)
        super.init(coder: aDecoder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        imageView.center = view.center
        view.addSubview(imageView)
    }
}

Example 2:

import UIKit

class ViewController: UIViewController {
    let image = UIImage(named: "Safari")
    var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        imageView = UIImageView(frame: view.bounds)
        imageView.image = image
        imageView.center = view.center
        view.addSubview(imageView)
    }
}
Marcus Rossel
  • 3,196
  • 1
  • 26
  • 41
Prince Sha
  • 57
  • 3
  • 1
    possible duplicate of [Why create "Implicitly Unwrapped Optionals"?](http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals) – ybakos Jan 31 '15 at 16:41

4 Answers4

0

In example 1, the variable value is set in init. In example 2, the variable is initialized later and after initialization (until viewDidLoad is called) its value is nil.

Since in example 1 the variable is never nil, it can be a non-optional. However, in example 2 the variable is nil for a long time, so it must be an optional variable.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
0

In swift all non optional class and struct properties must be initialized in a constructor, and there's no way to avoid that (unless it's initialized inline, along with its declaration).

In some cases a non optional property cannot be initialized at instantiation time, because it depends from other properties of the same class, or just it must be initialized at a later stage in the instance lifetime. As such, these properties must be declared as optional.

A workaround consists of declaring all there properties as implicitly unwrapped - internally they are optionals, but they are accessed as non optionals (i.e. without the ? operator).

That explains the differences between example 1 and 2: in the former, the property is initialized in the initializer, so it is declared as non optional. In the latter case instead it is initialized in the viewDidLoad method, and so it's been declared as implicitly unwrapped.

This pattern is widely used in view and view controller outlets - you will notice that when you create an outlet in IB, the corresponding property is an implicitly unwrapped - that's because the variable is assigned after initialization.

Antonio
  • 71,651
  • 11
  • 148
  • 165
0

As others have noted, the purpose of these two examples is to illustrate the difference between a non-optional variable that is set during the initialization process and an optional (in this case, an implicitly unwrapped one) which you may instantiate at a later point.

It's worth noting that while this example has pedagogic value, from a practical perspective, when dealing with view controllers, you would use the latter pattern with optional variable set in viewDidLoad (or for programmatically created views, you might use a third pattern, the loadView method), not the first pattern with the non-optional instantiated in init.

I just wanted to make sure you didn't walk away from this example concluding that in the case of view controllers that you should freely use either of these two patterns. There are reasons, unrelated to the Swift language but rather related to details of the life cycle of view controllers, views, etc., that you would favor the optional variable set in viewDidload when dealing with view controllers.

That notwithstanding, it is important to understand in what cases one would use an optional in Swift and in what cases one would not (the key point being that you must use optional if the variable may not be set during the initialization process of the object), so from that perspective, this may be an illuminating example. But just remember, that in the specific case of view controllers, one would generally adopt the viewDidLoad pattern.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    if you hadn't stated that, I would indeed have walked away thinking I had a choice between the two. I too have noticed the second pattern used extensively whilst only came across the first one in this book. So really do appreciate the help and pointing the above out. – Prince Sha Jan 31 '15 at 17:34
0

Example 1's only initializer is the required init(coder aDecoder: NSCoder), which always assignes a value to imageView. Therefore imageView will always have a value after initilization has taken place.

Example 2 doesn't have or need an initilizer, since both stored properties are given an initial value in their declaration:

let image = UIImage(named: "Safari") // has an initial value of whatever UIImage(named: "Safari") returns
var imageView: UIImageView! // has an initial value of nil

You can therefore construct a ViewController, by calling the initializer which swift adds automatically: ViewController()

This will result in imageView having a value of nil.

Marcus Rossel
  • 3,196
  • 1
  • 26
  • 41