Value of optional type "..." not unwrapped; did you mean to use '!' or '?'?
Can someone explain me what this error message exactly means? When should I use '?' and when '!'?
Outlets are a common example when discussing implicitly unwrapped optionals. Why does Apple use implicitly unwrapped optionals to declare outlets? The reason is simple. Every stored property of a class needs to have a valid value before the initialization of the instance is complete.
Checking an optionals value is called “unwrapping”, because we're looking inside the optional box to see what it contains. Implicitly unwrapping that optional means that it's still optional and might be nil, but Swift eliminates the need for unwrapping.
Unwrapping in Swift is essentially verifying if the Optional value is nil or not, and then it performs a task only if it's not nil. You can perform unwrapping in the following ways: Using an if else block. Using Forced unwrapping. Using Optional binding.
An Optional is a type on its own, actually one of Swift 4's new super-powered enums. It has two possible values, None and Some(T), where T is an associated value of the correct data type available in Swift 4.
obj?.fn()
calls fn
member function if the object isn't null, otherwise doesn't do anything.
obj!.fn()
on the other hand asserts that obj
isn't null, and calls fn
. If the object is null, you get an exception.
So it's a difference in assertiveness: you either ask or simply claim the nullable property of a nullable object.
What is a String?
. Is it a String that is optional or is it an optional that 'has an associated value of String'.
Only the 2nd definition is correct. To access any member/property on String or to run a function on a string you MUST do it on the 'associated value of the optional' which requires you to unwrap the optional.
I know of 2 ways that this error could be created:
1st
if you have
@IBOutlet weak var display : UILabel? // FYI IBOutlets must be optional...
let something = display.text // Line C
let something = display!.text // Line D
You will get the following error on line C:
Value of optional type 'UILabel?' not unwrapped; did you mean to use '!' or '?'?
This is because you are messaging text
onto an optional, but the optional itself doesn't have any understanding of text
method, however its 'unwrapped associated value'—UILabel!
can understand. Therefore you must write it as line D
Having that said the correct approach is to just unwrap UILabel from the beginning and then easily accessing its text as such:
@IBOutlet weak var display : UILabel!
let something = display.text
2nd
cell.textLabel?.text = bug.name // Line A: you are messaging text on *optional* textLabel
cell.textLabel.text = bug.name // Line B: you are messaging text on textLabel
on Line B you are accessing textLabel
which is an optional that has an associated type of UILabel.
It will create the following error:
Value of optional type 'UILabel?' not unwrapped; did you mean to use '!' or '?'?
You can go to UITableViewCell.swift
and see that it is declared as:
public var textLabel: UILabel? { get } // default is nil. label will be created if necessary.
UILabel?
is a property in an optional form.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With