When confronting the error fatal error:
Can't unwrap Optional.None
It is not that easy to trace this. What causes this error?
Code:
import UIKit
class WelcomeViewController: UIViewController {
let cornerRad:CGFloat = 10.0
#IBOutlet var label:UILabel
#IBOutlet var lvl1:UIButton
#IBOutlet var lvl2:UIButton
#IBOutlet var lvl3:UIButton
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
override func viewDidLoad() {
super.viewDidLoad()
lvl1.layer.cornerRadius = cornerRad
lvl2.layer.cornerRadius = cornerRad
lvl3.layer.cornerRadius = cornerRad
}
}
You get this error, because you try to access a optional variable, which has no value.
Example:
// This String is an optional, which is created as nil.
var optional: String?
var myString = optional! // Error. Optional.None
optional = "Value"
if optional {
var myString = optional! // Safe to unwrap.
}
You can read more about optionals in the official Swift language guide.
When you see this error this is due to an object such as an unlinked IBOutlet being accessed. The reason it says unwrap is because when accessing an optional object most objects are wrapped in such a way to allow the value of nil and when accessing an optional object you are "unwrapping" the object to access its value an this error denotes there was no value assigned to the variable.
For example in this code
var str:String? = nil
var empty = str!.isEmpty
The str variable is declared and the ? denotes that it can be null hence making it an OPTIONAL variable and as you can see it is set to nil. Then it creates a inferred boolean variable empty and sets it to str!.isEmpty which the ! denotes unwrap and since the value is nil you will see the
Can't unwrap Optional.None error
Fisrt check your storyboard UILabel connection. wheather your UILabel Object or connected or Not. If not it showing Fatal Error.
Related
This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 3 years ago.
I need to take the response of the alamofire closure and send it to another class. I get the response inside the closure but when I try to send to the other class, I get: "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
I need to get the response from the closure and set it in a IBOutlet from another class.
Also I try to set the closure response in a variable global and I get the same error.
class DrawInformationViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
}
class RequestViewController: UIViewController{
var getName: String?
func testAlamofire(){
if let JSON = response.result.value{
self.jsonArray = JSON as? NSArray
//this for doesn't matter it is just for an example, to get the idea
for item in self.jsonArray! as! [NSDictionary]{
let name = item["name"] as? String
print(name) //until here everything is ok
//the problem is when I try to send this value
DrawInformationViewController().nameLabel.text = name //here is when it get the error: "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
//Also I try to set the value in a global var
getName = name //There is not problem
}
}
}
}
func setValueFromClosure(){
DrawInformationViewController().nameLabel.text = getName
//Here I get the same error: "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
}
}
Try initializing getName as follows:
var getName: String = ""
Cheers.
I'm confused why the label.text = textField.text line works even though textField.text is an optional. Generally I'd write it as:
if let text2 = textField.text {
label.text = text2
}
The above code works fine but why does the label.text = textField.text work fine too? I thought it's a must to unwrap optionals? When must I use the if let syntax and when do I not have to?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
label.text = ""
}
#IBAction func setTextButtonTapped(_ sender: Any) {
label.text = textField.text
}
#IBAction func clearTextButtonTapped(_ sender: Any) {
textField.text = ""
label.text = ""
}
}
UILabel text is an optional String.
UITextField text is an optional String.
An optional can accept an optional or a non-optional.
A non-optional can only accept a non-optional.
You only need to unwrap an optional when you need a non-optional from it.
As vacawama pointed out:
You can assign an optional to an optional; you can assign a
non-optional to an optional, but you cannot assign an optional to a
non-optional.
So you need to unwrap the optional if you wanted to assign it to a non-optional.
And to unwrap an optional, it's always safer to use if let statement, which extracts the non-optional version of the optional and assign it to a variable for further usage.
It sounds like you're not familiar with implicitly unwrapped optionals.
label is an implicitly unwrapped UILabel, and textField is an implicitly unwrapped UITextField
That's what the ! in the declaration
#IBOutlet weak var label: UILabel!
means.
Thus, it's legal to assign things to it without unwrapping it:
label.text = "some string"
However, that's not necessarily safe. If label is nil, that code will crash.
If label was a normal optional:
#IBOutlet weak var label: UILabel?
you'd have to use code like this:
label?.text = "some string"
Xcode sets up outlets as implicitly unwrapped optionals by default, since if an outlet is not connected, it's good to have your code crash so you know something is wrong.
Another part of this is that it's ok to compare 2 optionals with each other:
If you have
var a: Int?
var b: Int?
It's legal to test a == b. (Put formally, Optionals are Equatable.) That expression will evaluate to true if both are nil, or if both contain the same value. You'll get false if one is nil and the other contains a value, or if both contain different values.
(Note that optionals are not Comparable however. You could not use a < b, for example, since it's not define if nil > 0 or nil < 0.)
Yes, another found nil while unwrapping an Optional value error. I have read tons of other stack overflow posts with similar errors such as this one and many others. I still do not fully understand how to properly deal with unwrapping a variable.
I have a class that is similar to the following:
#IBOutlet weak var nameTextField: UITextField?
#IBOutlet weak var valueInput: UITextField?
var checkbox : CheckBox?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let name = nameTextField.text ?? ""
let state = buttonState.getIsChecked()
let value : Int? = Int(valueInput.text!)
let isMoveable = true
checkbox = CheckBox(name: name, value: value, state: state, isMoveable: isMoveable)
}
I get the error on the line the "let value : Int? = Int(valueInput.text!) line.
You can safely unwrap the value using if let construct
var value : Int? = nil
if let val = valueInput.text {
value = Int(val) // it would either nil or optional value
}
and also you can do it by nil coalescing operator ?? in a single line
let value : Int? = Int(valueInput.text ?? "")
UPDATE
First check if textfields disconnected from the Interface Builder , if not connect, connect them. and if you become your textfields optionals you also have to safely unwrap the textfields ( you forgot to add it from interface builder and it will not crash if you make them optionals).
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var name: String? = nil
var value : Int? = nil
let state = buttonState.getIsChecked()
let isMoveable = true
if let nameTextField = self.nameTextField where nameTextField.text != nil {
name = nameTextField.text!
}
if let valueTextField = self.valueInput where valueTextField.text != nil {
value = Int(valueTextField.text!)
}
checkbox = CheckBox(name: name, value: value, state: state, isMoveable: isMoveable)
}
Sahil's answer is on track, but doesn't address that valueInput is also an optional. Use this code:
if let valueInput = valueInput,
let val = valueInput.text {
value = Int(val)
}
In addition regarding properly unwrapping the optional valueInput I wanted to add that chances are that if valueInput is an IBOutlet it's defined as:
#IBOutlet weak var valueInput: UITextField!
That's called an implicitly unwrapped optional. The annoying thing is that since it is also an IBOutlet, if it ever becomes disconnected from the UITextField in Interface Builder, the variable will become nil, and accessing it from anywhere in the code will cause a crash.
Change it to this:
#IBOutlet weak var valueInput: UITextField?
I've also written about this on my blog: http://cleanswifter.com/implicitly-unwrapped-iboutlets/
Note: you didn't show the definition of valueInput so I assumed it to be a UITextField
In my UITableViewController, I have an optional property which is a CNContact. If not nil, I want to populate some text fields with the contact's data.
Here is the property:
var contact: CNContact? = nil {
didSet {
if contact != nil {
prefillFromContact(contact!)
}
}
}
And here is the code setting a text field
func prefillFromContact(con: CNContact) {
print(con.givenName)
firstNameTextField.text = con.givenName
}
The print statement works, and returns the contact's name, but the following line throws an error.
Kate
fatal error: unexpectedly found nil while unwrapping an Optional value
I can't work out why it works on the print statement, but not the following line.
I assume firstNameTextField is declared as an implicit optional, like this:
var firstNameTextField: UITextField!
And you are causing this code to be called before viewDidLoad.
If so, firstNameTextField is nil. It is only possible to set the values of UIViews loaded from XIB/Storyboards once they are loaded. Before that, their outlets are nil.
As an aside (even though this isn't what is causing your problem):
if contact != nil {
prefillFromContact(contact!)
}
is more Swifty like this:
if let contact = contact {
// this is only true if contact != nil, and you have a contact variable
// that is of type CNContact, not CNContact?
prefillFromContact(contact)
}
I add #IBAction for button:
#IBAction func addThemeAction(sender: AnyObject) {
var userDefaults:NSUserDefaults=NSUserDefaults.standardUserDefaults()
var itemList:NSMutableArray!=userDefaults.objectForKey("itemList") as NSMutableArray}
When I press button I get fatal error: unexpectedly found nil while unwrapping an Optional value.
There's no object for the key itemList in your NSUserDefaults. Instead of force unwrapping it with !, check if optional is nil and conditionally unwrap it:
let userDefaults = NSUserDefaults.standardUserDefaults()
var itemList = userDefaults.objectForKey("itemList") as? [AnyObject]
if let itemList = itemList {
// itemList is not nil, use it here
} else {
// itemList has never been set, perhaps use some default
}
Also, userDefaults doesn't need to be a var.
You can change [AnyObject] to something else if you know the type (like [String], for example).
One: You can never guarantee that some key is present in your user defaults, so this is a crash waiting to happen. Two: I don't think dictionaries that you read from user defaults are mutable.