Crash when unwrapping an optional, but I don't see any optional? - swift

I receive several crash reports:
Bugsnag:
VC.swift:290:34
Swift runtime failure: Unexpectedly found nil while implicitly unwrapping an Optional value
Apple Crash:
Line 290 has following code
func showFolders(path:String, topLevel:Bool = false, absolutePath:String) {
print("đź“‚ Get folder: " + path)
NetworkingService.shared.webdav.contentsOfDirectory(path: path, completionHandler: {
some code
})
}
The function 'showFolders' is called by following code which avoids to send any optional value:
let path = browser_relativePath?.absoluteString.removingPercentEncoding ?? ""
let topLevel = NetworkingService.shared.url_connected.hostOnly.withTrailingSlash == browser_absolutePath?.absoluteString
let absolutePath = browser_absolutePath?.path ?? ""
self.embeddedViewController.showFolders(path:path, topLevel: topLevel, absolutePath: absolutePath)
I don't understand how this might crash by "unwrapping an optional" when there is no optional in that part of the code... But I am probably blind ;-)
Can someone help me out ?

The clue is it says when implicitly unwrapping… so either NetworkingService.shared or NetworkingService.shared.webdav is declared as implicitly unwrapped and is nil when you call it

Related

Initializer for conditional binding must have Optional type, even if it is a Optional type

I got an error I do not understand, as I thought I understood unwrapping a conditional var/let. But when I try to force unwrap it in the if I get the supplied error.
Error:
Initializer for conditional binding must have Optional type, not 'String'
Code:
let imNotSet: String?
print(type(of: imNotSet)) // Optional<String>
if let unwrappedVar = imNotSet! { // error on this line
print(unwrappedVar)
}
if let unwrappedVar = imNotSet! { // error on this line
print(unwrappedVar)
}
imNotSet! forcefully unwrapped imNotSet. So it is no longer an optional but rather a string.
To keep it an optional, remove the forced unwrapping.
if let unwrappedVar = imNotSet { // error fixed
print(unwrappedVar)
}
if let allows you to safely unwrap the optional, unlike the forced unwrapping that you were doing before.
As for Constant 'imNotSet' used before being initialized error, Either provide it a value like let imNotSet: String? = "Sample", if it truly is a constant, before you use it. Or make it a var if you need to reset it later like var imNotSet: String? = nil
the var to be used with if let it must be an optional and this
imNotSet!
isn't , so replace
if let unwrappedVar = imNotSet! {
with
guard let unwrappedVar = imNotSet else { return }

optional unwrapping nil not always fatal error

Why does this piece of code give me an Fatal Error
var number: Int? = .none
print(number!)
Fatal error: Unexpectedly found nil while unwrapping an Optional value
But this piece of code does not?
var number: Int! = .none
print(number)
nil
Doesn't Int! automatically unwrap the variable on use? Why doesn't it throw a fatal error when number gets printed?
An Optional is a type that can hold or not a wrapped value.
In the first case, you're telling inside the code that numbers contains an Int variable (this is because of numbers!), which is a very unsafe way to work with Optionals. When you unwrap numbers, it has to contain a value or, on the contrary, has to not be nil. Since the compiler actually finds that there isn't an Int value but nil, so it calls fatal error.
In the second case, instead, you're simply printing an Optional, that can hold or not an Int value. In this specific case, it does not hold an Int value, so nil will be printed.
Here you can find more on Optionals:
https://developer.apple.com/documentation/swift/optional
Implicitly unwrapped optionals are still optionals under the hood; they just get automatically unwrapped as needed.
However, the print function accepts optional values, so unwrapping it there isn't needed. In the first case you get an error because you're explicitly unwrapping it, but in the second it's happy to keep it wrapped so there's no error. It'll work like that with other functions that accept optionals as well, but if you use it somewhere that an optional does not work, then it forces an unwrap and the behavior becomes the same for both:
let num1: Int! = nil
let num2: Int? = nil
print(String(describing: num1)) // works fine
print(String(describing: num2!)) // error
print(num1 + 1) // error
print(num2! + 1) // also error

What am I overlooking as I attempt to account for nil?

I've reread the Swift documentation a number of times, but I'm afraid I'm overlooking something simple here.
The function below processes just fine and properly calls the updateCalorieBalance method if there is value in the field caloriesConsumed.text. But, of course, crashes if caloriesConsumed.text is nil.
The error message I get is: fatal error: unexpectedly found nil while unwrapping an Optional value.
Your assistance is greatly appreciated.
#IBAction func buttonThree(sender: AnyObject) {
var calConsumed: String?
if let calConsumed = caloriesConsumed.text {
calorieCount.updateCalorieBalance(Double(calConsumed)!)
balanceLabel.text = "New Balance: \(Int((calorieCount.getCalorieBalance())))"
} else {
balanceLabel.text = "Please enter calories to add."
}
caloriesConsumed.resignFirstResponder()
}
calConsumed should not be an optional string. Actually, "if let" creates its own variable so you now have two variables with the same name...
Double (calConsumed) returns nil if calConsumed is an empty string or a string not containing a number. The ! that you use will make it crash.
if let calText = caloriesConsumed.text,
calNumber = Double (calText) {
...
}
(Not tested or even compiled).

Why use force unwrapping in this example?

let john = Person()
john.residence = Residence()
let johnsAddress = Address()
johnsAddress.buildingName = "The Larches"
johnsAddress.street = "Laurel Street"
john.residence!.address = johnsAddress
The above example is in Apple Language Guide.
Why did you use force unwrapping (exclamation mark) in the last line?
Is there a difference between ! and ? 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"

Can't unwrap Optional.None with AutoreleasingUnsafePointer

Upon running NSAppleScript.executeAndReturnError with an Applescript command that should fail and return an error, I get a Can't unwrap Optional.None error for errorDict.
var errorDict: NSDictionary? = nil
var scriptObject:NSAppleScript = NSAppleScript(source: command)
var execute:NSAppleEventDescriptor = scriptObject.executeAndReturnError(&errorDict)
I understand that the error is due to unwrapping a nil optional variable, though executeAndReturnError must take an optional variable. How could I fix this?
This error is most likely occurring while trying to initialize the NSAppleScript object, not your NSDictionary? object. NSAppleScript(source:) is a failable initializer, meaning it could return nil if an error occurs compiling your script. Your code should look something like this:
if let scriptObject = NSAppleScript(source: command) {
var errorDict: NSDictionary? = nil
let execute = scriptObject.executeAndReturnError(&errorDict)
if errorDict != nil {
// script execution failed, handle error
}
} else {
// script failed to compile, handle error
}
Sulthan's answer makes a good point, but as of Swift 1.2, executeAndReturnError(errorInfo:) no longer returns an Optional type even though it could return a nil (see this radar). The proper way to handle the execution failing is by checking the errorInfo dictionary for errors.