Can't unwrap Optional.None with AutoreleasingUnsafePointer - swift

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.

Related

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

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

Failure to catch an optional value equalling nil in conditional assignment

Trying to execute an update only on a non-nil string, but the following code seems to execute the conditional clause regardless of whether the text (string optional) has a value or not.
submitText is a UITextField and this code is executing on a press of a UIButton.
tvc.addTask expects one task argument of type String.
I've tried explicit and implicit unwrapping, both to no avail.
if let str = submitText.text {
print(str)
tvc.addTask(task: str)
}
I expected the code not to execute if the textField is empty but instead it gives me a "Unexpectedly found nil while implicitly unwrapping an Optional value" fatal error. However, the string prints out correctly based on what is entered in the textbox.
The text variable never equals to nil, it is optional only for reseting its value.
submitText.text = nil
Check like this
if !submitText.text.isEmpty {
tvc.addTask(task: submitText.text!)
}
tvc equals nil.
You are getting "Unexpectedly found nil while implicitly unwrapping an Optional value" fatal error maybe because (as per the above code) submitText is set to nil or tvc = nil.
Make sure your textField/tvc is initialised before extracting its value.
In your code,
if let str = submitText.text {
print(str)
tvc.addTask(task: str)
}
you will not get above error, if submitText.text = nil.

Is the question mark required?

I was reviewing the code of an ex-collegue, when I found this one:
if task != nil {
// why is "?" here?
task?.cancel()
task = nil
}
task is declared as an optional.
I'm supposing at that point task can't be nil anymore. So why the developer puts a question mark? Couldn't I insert an exclamation mark, instead?
Due to compiler hint the ? may be put by the compiler, not your colleague.
Instead, you could use an if let statement as follows:
if let task2 = task {
task2.cancel()
task = nil
}
The task is calling cancel() so that may be task is nil, here we notify to the compiler by ? for the task, If the compiler will get nil it goes silently without crashing.
Thanks for pointing this out but cancel is not mutating and task is a reference type
You've mentioned that task is a reference type, so the optional binding methods show in the other answers will be ok even due to the copying/binding that occurs when optionally binding and mutating a value. Note, however, that you needn't necessarily resort to optional binding to cover the logic in the snippet you've shown, but can instead simply combine the optional chaining and the nil check within a single conditional (and only setting the property to nil within the body of the conditional).
// if task is non-nil, cancel it and set it to 'nil'
// if task is already nil, do nothing
if task?.cancel() != nil { task = nil }
You should unwrap the value by doing: if let task = task if you want to avoid the question mark.
You can unwrap optional using Guard statements too
//This will not unwrap the optional. It will remain optional
if task != nil {
task?.cancel() //That is why the compiler added the question mark automatically
}
// This will unwrap the optional variable
guard let task2 = task else {
return
}
// task will be optional but task2 will not
task?.cancel()
task? = nil
task2.cancel()
task2 = nil
You can unwrap the optional using if let or guard, then you don't need ? or !

using guard to check for nil without implicitly unwrapping

I know there are some similar questions around, but I couldn't find one specific to my issue.
I have a request where I want to check for the presence of the error key. it is not present everything is fine, if not I should handle the error. Currently, I have it implemented as follows:
if let error = json["error"] {
// handle error
}
else {
// handle success
}
I would like to use a guard statement here to have the success case unindented. The only way I came up with is
guard json["error"] == nil else {
let error = json["error"]!
// handle error
}
// handle success
but that seems wrong to me with the !. Are there any other approaches to this?
In your guard code you would have to have a return statement in the else block. Like this...
guard json["error"] == nil else {
let error = json["error"]!
// handle error
return
}
// handle success
But you are correct. Having to force unwrap the error is not ideal.
So in this case. I think guard is the wrong solution. Instead use if but return from the conditional block. This removes the need for using an else block.
if let error = json["error"] {
print(error)
// handle error
return
}
// handle success...
// no need for else block. Just return from the if in the error case.
The difference between guard let and if let is where the unwrapped optional is scoped.
With guard it is scoped outside the block with if it is scoped inside the block.
An idea for your issue was proposed on the Swift Evolution mailing list:
"guard not let" optional binding
https://forums.swift.org/t/idea-guard-not-let-optional-binding/2614
[it is] fairly common that you want to check that an optional is nil, and still bail if it isn’t (maybe using the value that you now know exists), e.g:
guard cachedValue == nil else { return cachedValue! }
cachedValue = //… expensive calculation
It seems a little bit “unfair” that we have this lovely clean let syntax when checking for Optional.Some, but we to have to do this ugly manual check against nil and explicit unwrap when checking for Optional.None. There is literally no other way to satisfy the guard statement; our optional bindings only go one-way can’t be evaluated.
Unfortunately that construct does not currently exist in Swift.
The alternatives are the slightly awkward/duplicated guard syntax, possibly with a force-unwrap:
guard json["error"] == nil else {
return json["error"]!
}
or using if-let (which does not enforce scope-exit like guard):
if let error = json["error"] {
return error
}

Debugging nil optionals

Numerously in the past I have fixed the sporadic unexpectedly found nil while unwrapping an Optional value error, and I have just fixed one now; However the way I am doing it right now is through guessing where the nil optionals are via breakpoints.
There is always an EXC_BREAKPOINT under Swift._fatalErrorMessage (in the assembly) when an error like this is thrown for me.
Is there a more efficient method (like a exception catch) of jumping to the nil optional instead of guessing where it is with log messages and (inline) breakpoints?
Your crashes are almost certainly happening in a line where you're forcibly unwrapping an optional using !. Unless you're absolutely certain that a value exists, you should use if let instead.
Instead of:
let myValue = myArray[index]! // will crash if myArray[index] is nil
Use this:
if let myValue = myArray[index] {
println("myValue has a value and it is \(myValue)")
// Code using myValue
} else {
println("myValue is nil")
}
Edit: To answer your question directly, search for instances of ! and in general, replace them with if let or ?.