Purpose of Forced Unwrapping

Why use force unwrapping in this example?

A forced unwrapping is used when it's know that the optional has a non nil value. Using it on an optional with nil value generates a runtime exception.

The normal unwrapping instead is conditional. If john.residence is nil, then whatever is after it is ignored, and no error is generated (see Optional Chaining). The statement simply doesn't do anything, hence no assignment takes place.

The reason why the forced unwrapping exists is that it avoids checking for nils when it's known it has a value. For instance let's suppose you want to print to the console the content of a String variable:

let x: String?
print("\(x)")

If you initialize the variable instead, it will print something you wouldn't probably expect:

let x: String? = "Test"
print("\(x)") // Prints "Optional("Test")"

That happens because x is an Optional and not a String type.
To fix that, you force the unwrapping using the exclamation mark:

print("\(x!)") // Prints "Test"

How force unwrapping works in function parameters in Swift?

Here ! means the param will hold String value or nil. So when you assign nil to ! it is not supposed to crash.
But when you try to access that value, it will crash.

This modification in your code will cause a crash as we are trying to access the value inside the variable which is nil.

func getValue(param: String!) -> String {
if param.isEmpty {
return ""
}
return ""
}

let retVal = getValue(param: nil)

Another example:

var string: String!
string = nil //This will not crash, but after this line if you try to access or perform any operation on it, it will

Now about thisfunc getValue(param: String?) :

In this scenario the the param will be optional type unlike in the above scenario. So here you will have to unwrap it.

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

Why using implicit unwrap or force unwrap letting the app crash at some stage not beneficial?

Sure. There any many proper uses of force-unwrapping where a crash will only occur early in development because a mistake has been made and once fixed, the crash won't ever happen again.

A common example is accessing an image from the resource bundle. A line such as:

let imagePath = Bundle.main.path(forResource: "image", ofType: "png")!

should crash in early development if the developer forgot to target image.png properly. Once targeted properly, that line won't crash so there's no reason to deal with an optional path.

Other common examples are outlets. They are usually made implicitly unwrapped because by the time they are used in the view controller's code, they will have been attached. A crash probably means the outlet wasn't connected properly. It gets fixed and there's no more worry. No need to deal with guards or other optional checking.

Last example (there are many more possibilities). When dequeuing a cell from a table view, force-cast the resulting cell to the custom cell type. No need for a guard. I see code here all the time that uses a guard with as? to throw a fatal error if the cast fails. Just force-cast. You get the same crash with less code. Once the table view and storyboard are correct, the force-cast won't fail.

Having said this, newer Swift developers should avoid the ! character on their keyboard for a while. Knowing when to safely use it is a learned skill.

If the potential crash is fully in the control of the developer and the crash could only happen because the developer make a mistake, then using ! may be appropriate.

If the potential crash can be caused by unexpected data (JSON parsing, user input, etc.), then never use !. Code defensively in those cases.

tl;dr - yes, there are plenty of cases where forced-unwraps, forced-casts, and implicitly unwrapped variables are the correct choice.

What is the advantage of force unwrapping an optional?

Performance-wise there might be a very to very very small no difference between forced and optional binding/chaining, as the optional version might have an extra if somewhere.

But nonetheless when talking about performance issues, the performance bottlenecks come from other parts of the code, like non-improved loops, lots of accumulation NSNotification's sent in a short amount of time, unnecessary redraws of the UI, etc.

So it's best to stay on the safer side and use optional binding/casting/chaining and focus on the parts of the code that adds actual performance penalties. Even if at the time you write the code the value is guaranteed to be non-nil, in the future in might be that the conditions will change and you'll suddenly end up with crashes that you didn't expect they'll occur.

Swift has made it very easy to deal with optionals, without writing a lot of boilerplate code, you should take advantage of those features.

Forced unwrap of a return type?

func myFunction() -> NSData { ... }

The above means that myFunction returns an instance of NSData.


func myFunction() -> NSData? { ... }

The above means that myFunction returns a value of type Optional<NSData> (also called NSData?). Optional is an enum with two cases: .some(value) and .none (also called nil). So the function returns either an NSData (wrapped in the .some case), or nil.


func myFunction() -> NSData! { ... }

The above means that myFunction returns a value of type Optional<NSData>, just like the NSData? return type in the previous example.

However, the use of ! means that, if you use the value of myFunction() in a way that doesn't type-check, the compiler will try unwrapping the returned value for you. So if you say this:

let maybeLength = myFunction()?.length

then the compiler will see that you are treating the return value of myFunction as an Optional<NSData>. But if you say this:

let dataLength = myFunction().length

then the compiler will see that Optional<NSData> doesn't have a length member, so it will pretend you wrote this:

let dataLength = myFunction()!.length

and if that compiles, it will carry on.

This behavior was defined in Swift Evolution proposal SE-0054, Abolish ImplicitlyUnwrappedOptional type.


Now let's finally consider this:

func myFunction() -> NSData! { ... }
let data = myFunction()
data?.write()

What is the type of data? The compiler has to infer the type of data based on the expression on the right side of the =. As I explained in the example above, the type of myFunction() is Optional<NSData>. So the type of data is Optional<NSData>, also called NSData?.

The compiler doesn't run into any trouble making data's type NSData?, so it has no reason to implicitly unwrap the return value of myFunction.

swift - Implicit unwrapped optionals

It's all related to the class initialization.

take Outlets for example they're force unwrapped because we know they will hold a value after initialization from the XIB or Storyboard but they will not be set before the class initialization.

A force unwrapped optional exits to tell the compiler I'm taking the responsibility to make sure this variable will be set before calling it.

in your example I don't think it makes sense to write:

let aString: String! = "this is a test string"

It should just be as you wrote:

let aString: String = "this is a test string"

It makes more sense to have:

var aString: String!

meaning you'll take ownership of this variable initialization (i.e making sure it's not nil)

How to use 🧨 for forced unwrap in Swift 5.0 / Xcode

As discussed in the comments & Matt's answer, the character is not available to be an operator, so if you specifically want to use it, then you can do it with an extension as seen here.

extension Optional {
var : Wrapped {
return self!
}
}

var string: String? = "42"
print(string.) // 42

var number: Int? = nil
print(number.) // Fatal error: Unexpectedly found nil while unwrapping an Optional value

This extension makes use of the Optional type, so it can be used with any data type that conforms to Optional.

However, if you want to the postfix route, then the following offers an option:

postfix operator ☠
extension Optional {
postfix static func ☠(optional: Optional<Wrapped>) -> Wrapped {
return optional!
}
}

var bad: String?
print(bad☠)

Sadly, the skull & crossbones do not show as well here as they do in Xcode.

Sample Image

On a serious note for OP, if you wish to enforce usage of this within a team, I would recommend a tool such as swiftlint, where you can modify the rules around force unwrapping to require some .



Related Topics



Leave a reply



Submit