Tuesday, July 5, 2022
HomeiOS Developmentswift - What does "Deadly error: Unexpectedly discovered nil whereas unwrapping an...

swift – What does “Deadly error: Unexpectedly discovered nil whereas unwrapping an Non-compulsory worth” imply?


Background: What’s an Non-compulsory?

In Swift, Non-compulsory<Wrapped> is an choice sort: it could actually include any worth from the unique (“Wrapped”) sort, or no worth in any respect (the particular worth nil). An non-obligatory worth should be unwrapped earlier than it may be used.

Non-compulsory is a generic sort, which signifies that Non-compulsory<Int> and Non-compulsory<String> are distinct sorts — the sort inside <> known as the Wrapped sort. Underneath the hood, an Non-compulsory is an enum with two circumstances: .some(Wrapped) and .none, the place .none is equal to nil.

Optionals could be declared utilizing the named sort Non-compulsory<T>, or (mostly) as a shorthand with a ? suffix.

var anInt: Int = 42
var anOptionalInt: Int? = 42
var anotherOptionalInt: Int?  // `nil` is the default when no worth is supplied
var aVerboseOptionalInt: Non-compulsory<Int>  // equal to `Int?`

anOptionalInt = nil // now this variable incorporates nil as a substitute of an integer

Optionals are a easy but highly effective instrument to specific your assumptions whereas writing code. The compiler can use this data to stop you from making errors. From The Swift Programming Language:

Swift is a type-safe language, which implies the language lets you be clear concerning the varieties of values your code can work with. If a part of your code requires a String, sort security prevents you from passing it an Int by mistake. Likewise, sort security prevents you from by accident passing an non-obligatory String to a bit of code that requires a non-optional String. Kind security helps you catch and repair errors as early as doable within the growth course of.

Another programming languages even have generic choice sorts: for instance, Possibly in Haskell, choice in Rust, and non-obligatory in C++17.

In programming languages with out choice sorts, a specific “sentinel” worth is usually used to point the absence of a legitimate worth. In Goal-C, for instance, nil (the null pointer) represents the shortage of an object. For primitive sorts resembling int, a null pointer cannot be used, so that you would want both a separate variable (resembling worth: Int and isValid: Bool) or a delegated sentinel worth (resembling -1 or INT_MIN). These approaches are error-prone as a result of it is simple to overlook to examine isValid or to examine for the sentinel worth. Additionally, if a specific worth is chosen because the sentinel, which means it could actually not be handled as a legitimate worth.

Possibility sorts resembling Swift’s Non-compulsory remedy these issues by introducing a particular, separate nil worth (so you do not have to designate a sentinel worth), and by leveraging the sturdy sort system so the compiler can assist you bear in mind to examine for nil when obligatory.


Why did I get “Deadly error: Unexpectedly discovered nil whereas unwrapping an Non-compulsory worth”?

With the intention to entry an non-obligatory’s worth (if it has one in any respect), you have to unwrap it. An non-obligatory worth could be unwrapped safely or forcibly. If you happen to force-unwrap an non-obligatory, and it did not have a price, your program will crash with the above message.

Xcode will present you the crash by highlighting a line of code. The issue happens on this line.

crashed line

This crash can happen with two totally different sorts of force-unwrap:

1. Specific Power Unwrapping

That is achieved with the ! operator on an non-obligatory. For instance:

let anOptionalString: String?
print(anOptionalString!) // <- CRASH

Deadly error: Unexpectedly discovered nil whereas unwrapping an Non-compulsory worth

As anOptionalString is nil right here, you’re going to get a crash on the road the place you power unwrap it.

2. Implicitly Unwrapped Optionals

These are outlined with a !, quite than a ? after the sort.

var optionalDouble: Double!   // this worth is implicitly unwrapped wherever it is used

These optionals are assumed to include a price. Due to this fact everytime you entry an implicitly unwrapped non-obligatory, it would mechanically be power unwrapped for you. If it doesn’t include a price, it would crash.

print(optionalDouble) // <- CRASH

Deadly error: Unexpectedly discovered nil whereas implicitly unwrapping an Non-compulsory worth

With the intention to work out which variable brought about the crash, you’ll be able to maintain whereas clicking to point out the definition, the place you would possibly discover the non-obligatory sort.

IBOutlets, particularly, are normally implicitly unwrapped optionals. It is because your xib or storyboard will hyperlink up the shops at runtime, after initialization. It’s best to due to this fact be sure that you’re not accessing shops earlier than they’re loaded in. You additionally ought to examine that the connections are appropriate in your storyboard/xib file, in any other case the values will probably be nil at runtime, and due to this fact crash when they’re implicitly unwrapped. When fixing connections, attempt deleting the strains of code that outline your shops, then reconnect them.


When ought to I ever power unwrap an Non-compulsory?

Specific Power Unwrapping

As a normal rule, you need to by no means explicitly power unwrap an non-obligatory with the ! operator. There could also be circumstances the place utilizing ! is suitable – however you need to solely ever be utilizing it if you’re 100% positive that the non-obligatory incorporates a price.

Whereas there might be an event the place you need to use power unwrapping, as you understand for a truth that an non-obligatory incorporates a price – there may be not a single place the place you can not safely unwrap that non-obligatory as a substitute.

Implicitly Unwrapped Optionals

These variables are designed so to defer their task till later in your code. It’s your accountability to make sure they’ve a price earlier than you entry them. Nonetheless, as a result of they contain power unwrapping, they’re nonetheless inherently unsafe – as they assume your worth is non-nil, although assigning nil is legitimate.

It’s best to solely be utilizing implicitly unwrapped optionals as a final resort. If you need to use a lazy variable, or present a default worth for a variable – you need to achieve this as a substitute of utilizing an implicitly unwrapped non-obligatory.

Nonetheless, there are a few situations the place implicitly unwrapped optionals are useful, and you might be nonetheless ready to make use of varied methods of safely unwrapping them as listed under – however you need to all the time use them with due warning.


How can I safely cope with Optionals?

The only solution to examine whether or not an non-obligatory incorporates a price, is to match it to nil.

if anOptionalInt != nil {
    print("Comprises a price!")
} else {
    print("Doesn’t include a price.")
}

Nonetheless, 99.9% of the time when working with optionals, you’ll truly wish to entry the worth it incorporates, if it incorporates one in any respect. To do that, you need to use Non-compulsory Binding.

Non-compulsory Binding

Non-compulsory Binding permits you to examine if an non-obligatory incorporates a price – and permits you to assign the unwrapped worth to a brand new variable or fixed. It makes use of the syntax if let x = anOptional {...} or if var x = anOptional {...}, relying if you have to modify the worth of the brand new variable after binding it.

For instance:

if let quantity = anOptionalInt {
    print("Comprises a price! It's (quantity)!")
} else {
    print("Doesn’t include a quantity")
}

What this does is first examine that the non-obligatory incorporates a price. If it does, then the ‘unwrapped’ worth is assigned to a brand new variable (quantity) – which you’ll then freely use as if it have been non-optional. If the non-obligatory doesn’t include a price, then the else clause will probably be invoked, as you’ll count on.

What’s neat about non-obligatory binding, is you’ll be able to unwrap a number of optionals on the similar time. You may simply separate the statements with a comma. The assertion will succeed if all of the optionals have been unwrapped.

var anOptionalInt : Int?
var anOptionalString : String?

if let quantity = anOptionalInt, let textual content = anOptionalString {
    print("anOptionalInt incorporates a price: (quantity). And so does anOptionalString, it’s: (textual content)")
} else {
    print("A number of of the optionals don’t include a price")
}

One other neat trick is that you could additionally use commas to examine for a sure situation on the worth, after unwrapping it.

if let quantity = anOptionalInt, quantity > 0 {
    print("anOptionalInt incorporates a price: (quantity), and it’s larger than zero!")
}

The one catch with utilizing non-obligatory binding inside an if assertion, is that you could solely entry the unwrapped worth from inside the scope of the assertion. If you happen to want entry to the worth from outdoors of the scope of the assertion, you need to use a guard assertion.

A guard assertion permits you to outline a situation for achievement – and the present scope will solely proceed executing if that situation is met. They’re outlined with the syntax guard situation else {...}.

So, to make use of them with an non-obligatory binding, you are able to do this:

guard let quantity = anOptionalInt else {
    return
}

(Word that inside the guard physique, you should use one of many management switch statements in an effort to exit the scope of the at present executing code).

If anOptionalInt incorporates a price, will probably be unwrapped and assigned to the brand new quantity fixed. The code after the guard will then proceed executing. If it doesn’t include a price – the guard will execute the code inside the brackets, which is able to result in switch of management, in order that the code instantly after is not going to be executed.

The actual neat factor about guard statements is the unwrapped worth is now out there to make use of in code that follows the assertion (as we all know that future code can solely execute if the non-obligatory has a price). This can be a nice for eliminating ‘pyramids of doom’ created by nesting a number of if statements.

For instance:

guard let quantity = anOptionalInt else {
    return
}

print("anOptionalInt incorporates a price, and it’s: (quantity)!")

Guards additionally help the identical neat tips that the if assertion supported, resembling unwrapping a number of optionals on the similar time and utilizing the the place clause.

Whether or not you employ an if or guard assertion fully will depend on whether or not any future code requires the non-obligatory to include a price.

Nil Coalescing Operator

The Nil Coalescing Operator is a nifty shorthand model of the ternary conditional operator, primarily designed to transform optionals to non-optionals. It has the syntax a ?? b, the place a is an non-obligatory sort and b is identical sort as a (though normally non-optional).

It primarily enables you to say “If a incorporates a price, unwrap it. If it doesn’t then return b as a substitute”. For instance, you might use it like this:

let quantity = anOptionalInt ?? 0

It will outline a quantity fixed of Int sort, that can both include the worth of anOptionalInt, if it incorporates a price, or 0 in any other case.

It’s simply shorthand for:

let quantity = anOptionalInt != nil ? anOptionalInt! : 0

Non-compulsory Chaining

You should utilize Non-compulsory Chaining in an effort to name a way or entry a property on an non-obligatory. That is merely achieved by suffixing the variable title with a ? when utilizing it.

For instance, say we have now a variable foo, of sort an non-obligatory Foo occasion.

var foo : Foo?

If we needed to name a way on foo that doesn’t return something, we will merely do:

foo?.doSomethingInteresting()

If foo incorporates a price, this technique will probably be known as on it. If it doesn’t, nothing dangerous will occur – the code will merely proceed executing.

(That is related behaviour to sending messages to nil in Goal-C)

This may due to this fact even be used to set properties in addition to name strategies. For instance:

foo?.bar = Bar()

Once more, nothing dangerous will occur right here if foo is nil. Your code will merely proceed executing.

One other neat trick that non-obligatory chaining enables you to do is examine whether or not setting a property or calling a way was profitable. You are able to do this by evaluating the return worth to nil.

(It is because an non-obligatory worth will return Void? quite than Void on a way that doesn’t return something)

For instance:

if (foo?.bar = Bar()) != nil {
    print("bar was set efficiently")
} else {
    print("bar wasn’t set efficiently")
}

Nonetheless, issues turn out to be a bit bit extra tough when making an attempt to entry properties or name strategies that return a price. As a result of foo is non-obligatory, something returned from it would even be non-obligatory. To cope with this, you’ll be able to both unwrap the optionals that get returned utilizing one of many above strategies – or unwrap foo itself earlier than accessing strategies or calling strategies that return values.

Additionally, because the title suggests, you’ll be able to ‘chain’ these statements collectively. Because of this if foo has an non-obligatory property baz, which has a property qux – you might write the next:

let optionalQux = foo?.baz?.qux

Once more, as a result of foo and baz are non-obligatory, the worth returned from qux will all the time be an non-obligatory no matter whether or not qux itself is non-obligatory.

map and flatMap

An usually underused function with optionals is the power to make use of the map and flatMap features. These permit you to apply non-optional transforms to non-obligatory variables. If an non-obligatory has a price, you’ll be able to apply a given transformation to it. If it doesn’t have a price, it would stay nil.

For instance, let’s say you could have an non-obligatory string:

let anOptionalString:String?

By making use of the map operate to it – we will use the stringByAppendingString operate in an effort to concatenate it to a different string.

As a result of stringByAppendingString takes a non-optional string argument, we can not enter our non-obligatory string immediately. Nonetheless, by utilizing map, we will use enable stringByAppendingString for use if anOptionalString has a price.

For instance:

var anOptionalString:String? = "bar"

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // Non-compulsory("foobar")

Nonetheless, if anOptionalString doesn’t have a price, map will return nil. For instance:

var anOptionalString:String?

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // nil

flatMap works equally to map, besides it permits you to return one other non-obligatory from inside the closure physique. This implies you’ll be able to enter an non-obligatory right into a course of that requires a non-optional enter, however can output an non-obligatory itself.

attempt!

Swift’s error dealing with system could be safely used with Do-Strive-Catch:

do {
    let consequence = attempt someThrowingFunc() 
} catch {
    print(error)
}

If someThrowingFunc() throws an error, the error will probably be safely caught within the catch block.

The error fixed you see within the catch block has not been declared by us – it is mechanically generated by catch.

You can even declare error your self, it has the benefit of with the ability to forged it to a helpful format, for instance:

do {
    let consequence = attempt someThrowingFunc()    
} catch let error as NSError {
    print(error.debugDescription)
}

Utilizing attempt this manner is the right solution to attempt, catch and deal with errors coming from throwing features.

There’s additionally attempt? which absorbs the error:

if let consequence = attempt? someThrowingFunc() {
    // cool
} else {
    // deal with the failure, however there isn't any error data out there
}

However Swift’s error dealing with system additionally supplies a solution to “power attempt” with attempt!:

let consequence = attempt! someThrowingFunc()

The ideas defined on this put up additionally apply right here: if an error is thrown, the applying will crash.

It’s best to solely ever use attempt! for those who can show that its consequence won’t ever fail in your context – and that is very uncommon.

More often than not you’ll use the entire Do-Strive-Catch system – and the non-obligatory one, attempt?, within the uncommon circumstances the place dealing with the error will not be essential.


Sources

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments