How to Declare Swift Implicitly Unwrapped Optional as a Constant

Implicitly Unwrapped Optional when a constant that cannot be defined during initialisation, But Error Comes

The important part is here:

City(name: capitalName, country: self)

You are definitely using self in the expression which is executed before the assignment to the property capitalCity.

If you want to use self in any of the expressions, it needs to be in the second phase of two phase initialization, which means all properties needs to be initialized before the usage of self.

With using var, Swift assigns a default initial value nil for the property capitalCity. So the property can be considered as "already initialized", so, you can use self after you have initialized another property name.

(You know giving nil to a let-constant of ImplicitlyUnwrappedOptional is ridiculous.)

By the way private(set) var is often used in similar cases:

    private(set) var capitalCity: City!

Why create Implicitly Unwrapped Optionals , since that implies you know there's a value?

Consider the case of an object that may have nil properties while it's being constructed and configured, but is immutable and non-nil afterwards (NSImage is often treated this way, though in its case it's still useful to mutate sometimes). Implicitly unwrapped optionals would clean up its code a good deal, with relatively low loss of safety (as long as the one guarantee held, it would be safe).

(Edit) To be clear though: regular optionals are nearly always preferable.

Implicitly Unwrapped Optionals in Swift does not seem to work

let statements don't have default initialization of optionals to nil, because otherwise writing let foo:Bar! would give you a foo that was always nil and you couldn't initialize it in a subsequent statement.

The reason var is appropriate is that you want default initialization to nil to occur so you can initialize your City object with the self reference in order to finally initialize your actual capitalCity value which is really double initialization.

The code has a circular class dependency by design, so this is a side effect of that design.

This behavior of let is new in Swift 1.2, try the example in Xcode 6.2 or earlier and you will find that it compiles.

Initialize a variable with nil vs implicitly unwrapped optional

Your code will simply not compile. Here's why.

By specifying var capitalCity: City, you're explicitly saying that your variable is non-optional. It can only ever hold a valid City. It can never be optional, so it can never hold nil.

Meanwhile, anytime you use ? or !, you are defining an optional type. These can be nil, and in fact are nil by default.

So in your example from the guide, var capitalCity: City! is saying the following:

  • capitalCity is declared as an implicitly unwrapped optional type (the !), meaning that you, as the developer, are declaring it to always have a valid City type whenever it is called.
  • That said, until you set a City to it, it defaults to being nil.

When you should use optionals comes down to how you want to use your properties. In the original example, from what little we see, capitalCity is only set in the class init. So there wouldn't be a reason for it to be optional. So for that example, it could exist like the other property: let capitalCity: City.

A lot depends on how you want the properties to exist and work when you're using your object. For instance, making something optional signals at least two things:

  1. The property may not have a valid value in the class' lifecycle.
  2. You may not be setting it when you initialize your class. (Remember, an optional initializes to nil)

I hope this helps you understand optionals some more.

Implicitly Unwrapped Optionals in Initialization - Swift

I'd stay away from implicitly unwrapped optionals unless there is a good reason to use them. Use non optional, when possible, otherwise optionals. Implicitly unwrapped are very dangerous if improperly used because they bypass the compiler check and generate runtime exceptions.

Non exhaustive list of cases when to use implicitly unwrapped:

  • when there's an API returning an implicitly unwrapped
  • to solve the Strong Reference Cycles Between Class Instances problem
  • when you have a class/struct property that (by design) will never be nil, but it cannot be set in the initializer

A typical case of the latter usage is in a UIViewController, when a property is initialized in the viewDidLoad method rather than in an initializer - it makes sense to use an implicitly unwrapped.

Do not use implicitly unwrapped in this cases:

  • because it's cool
  • because it lets you save a key press on the keyboard
  • when you are not 100% sure whether to use it or not

In your specific case, although the properties are instantiated in the initializator, they depend from the superclass initialization, so it makes sense to declare them as implicitly unwrapped.

Difference between Force Unwrapping Optionals and Implicitly Unwrapped Optionals


First of all let's define an Optional

An Optional value is a container of some type (Int, String, UIColor, ...), it could contain the value (1, "Hello world", .greenColor(), ...) or nil.

let anOptionalInt: Int? = 1
let anotherOptionalInt: Int? = nil

Sample Image

When in Swift we see an Optional value we think:

Ok this could contain the actual value or nil

Force unwrapping

It's the action of extracting the value contained inside an Optional.
This operation is dangerous because you are telling the compiler: I am sure this Optional value does contain a real value, extract it!

let anOptionalInt: Int? = 1
let anInt: Int = anOptionalInt!

Now anInt contains the value 1.

Sample Image

If we perform a force unwrapping on an Optional value that happens to contain nil we get a fatalError, the app does crash and there is no way to recover it.

let anotherOptionalInt: Int? = nil
let anotherInt = anotherOptionalInt!

fatal error: unexpectedly found nil while unwrapping an Optional value

Sample Image

Implicitly unwrapped optionals

When we define an Implicitly unwrapped optional, we define a container that will automatically perform a force unwrap each time we read it.

var text: String! = "Hello"

If now we read text

let name = text

we don't get an Optional String but a plain String because text automatically unwrapped it's content.

However text is still an optional so we can put a nil value inside it

text = nil

But as soon as we read it (and it contains nil) we get a fatal error because we are unwrapping an optional containing nil

let anotherName = text

fatal error: unexpectedly found nil while unwrapping an Optional value


Related Topics



Leave a reply



Submit