It may be the basic swift quetion, But i am new to swift or iOS development. I am getting the error fatal error: unexpectedly found nil while unwrapping an Optional value<
Well, error says it all! You are trying to forceful unwrap an optional. You should use if let
syntax while unwrapping an optional.
Optionals in swift can be confusing at first but it helps to keep in mind that they are just an enum like:
enum Optional<T> {
case None
case Some(T) // swift enums can have data associated to them
}
If you are sure your optional has non-nil value, that is, it is a .Some
, you can access this underlying value through the exclamation mark !
operator.
In short, force-unwrapping optional!
is saying "Ok, I'm sure this optional contains non-nil value. Give it to me."
This is what's called force-unwrapping. You're telling the system to access the value corresponding to .Some(T)
although you're not checking whether your optional is a .Some
or a .None
. If you force-unwrap with !
and your optional turns out to be a .None
, you will get the runtime error you got unexpectedly found nil while unwrapping an Optional value
.
As a rule of thumb you should always check your optionals before unwrapping them. In few occasions you should assume an optional is non-nil and force-unwrap it. Even an IBOutlet
can turn out to be nil
if you try to access it in prepareForSegue
for example. XCode automatically makes outlets implicitly unwrapped because for most of your view controller's lifecycle they won't be nil. But you still have to take care for yourself of these less common edge cases in which they are nil.
You can check if an optional has non-nil value the standard way with
if optional != nil {
// force-unwrapping after nil check is fine
optional!.someMethod()
} else {
// 'optional' is nil
}
A more idiomatic way to do it with swift is through optional binding.
// binds the constant 'value' to your optional if it is non-nil
if let value = optional {
value.someMethod()
} else {
// optional is nil
}
A third way to check is with guard statements. The semantics of guard statements is a bit different from the previous ones though. You can also mix guard statements and optional binding.
guard optional != nil else {
// optional is nil.
// by the end of this branch you must exit the block that
// encloses the guard statement, such as with a return or break
return
}
// if control reaches here you're guaranteed optional is non-nil
Guard statements are a neat feature in swift because you can focus on the conditions you want, as opposed to what you don't want. It also keeps the code that handles a violated requirement next to the respective requirement. Compared to doing the same thing with an if statement, guards improve readability by making your intents explicit.
To know more have a look at the basics section of the swift documentation.
You declared nilObj
as optional and initialised it with nil
. Then in your else
clause you are trying to unwrap that. For fixing the issue you just need to remove that !
Change your code to:
func Call() -> NSData?
{
let nilObj: NSData? = nil
if(false)
{
// Doing something
}
else
{
return nilObj
}
}