What does an exclamation mark mean in the Swift language?
What does it mean to "unwrap the instance"? Why is it necessary?
As far as I can work out (this is very new to me, too)...
The term "wrapped" implies we should think of an Optional variable as a present, wrapped in shiny paper, which might (sadly!) be empty.
When "wrapped", the value of an Optional variable is an enum with two possible values (a little like a Boolean). This enum describes whether the variable holds a value (Some(T)
), or not (None
).
If there is a value, this can be obtained by "unwrapping" the variable (obtaining the T
from Some(T)
).
How is
john!.apartment = number73
different fromjohn.apartment = number73
? (Paraphrased)
If you write the name of an Optional variable (eg text john
, without the !
), this refers to the "wrapped" enum (Some/None), not the value itself (T). So john
isn't an instance of Person
, and it doesn't have an apartment
member:
john.apartment
// 'Person?' does not have a member named 'apartment'
The actual Person
value can be unwrapped in various ways:
- "forced unwrapping":
john!
(gives thePerson
value if it exists, runtime error if it is nil) - "optional binding":
if let p = john { println(p) }
(executes theprintln
if the value exists) - "optional chaining":
john?.learnAboutSwift()
(executes this made-up method if the value exists)
I guess you choose one of these ways to unwrap, depending upon what should happen in the nil case, and how likely that is. This language design forces the nil case to be handled explicitly, which I suppose improves safety over Obj-C (where it is easy to forget to handle the nil case).
Update:
The exclamation mark is also used in the syntax for declaring "Implicitly Unwrapped Optionals".
In the examples so far, the john
variable has been declared as var john:Person?
, and it is an Optional. If you want the actual value of that variable, you must unwrap it, using one of the three methods above.
If it were declared as var john:Person!
instead, the variable would be an Implicitly Unwrapped Optional (see the section with this heading in Apple's book). There is no need to unwrap this kind of variable when accessing the value, and john
can be used without additional syntax. But Apple's book says:
Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable.
Update 2:
The article "Interesting Swift Features" by Mike Ash gives some motivation for optional types. I think it is great, clear writing.
Update 3:
Another useful article about the implicitly unwrapped optional use for the exclamation mark: "Swift and the Last Mile" by Chris Adamson. The article explains that this is a pragmatic measure by Apple used to declare the types used by their Objective-C frameworks which might contain nil. Declaring a type as optional (using ?
) or implicitly unwrapped (using !
) is "a tradeoff between safety and convenience". In the examples given in the article, Apple have chosen to declare the types as implicitly unwrapped, making the calling code more convenient, but less safe.
Perhaps Apple might comb through their frameworks in the future, removing the uncertainty of implicitly unwrapped ("probably never nil") parameters and replacing them with optional ("certainly could be nil in particular [hopefully, documented!] circumstances") or standard non-optional ("is never nil") declarations, based on the exact behaviour of their Objective-C code.
Swift variable decorations with ? (question mark) and ! (exclamation mark)
In a type declaration the !
is similar to the ?
. Both are an optional, but the !
is an "implicitly unwrapped" optional, meaning that you do not have to unwrap it to access the value (but it can still be nil).
This is basically the behavior we already had in objective-c. A value can be nil, and you have to check for it, but you can also just access the value directly as if it wasn't an optional (with the important difference that if you don't check for nil you'll get a runtime error)
// Cannot be nil
var x: Int = 1
// The type here is not "Int", it's "Optional Int"
var y: Int? = 2
// The type here is "Implicitly Unwrapped Optional Int"
var z: Int! = 3
Usage:
// you can add x and z
x + z == 4
// ...but not x and y, because y needs to be unwrapped
x + y // error
// to add x and y you need to do:
x + y!
// but you *should* do this:
if let y_val = y {
x + y_val
}
Exclamation mark prefix on variables during if statements and other as well?
the exclamation mark !
is used for two purposes. When you see it appear at the beginning of an object, such as in !contains(items, values)
, it means "NOT". For example...
let x = 10
let y = 5
if x == y {
print("x is equal to y")
} else if x != y {
print("x is NOT equal to y")
}
The above code will print => "x is NOT equal to y
" .
The logical NOT (!
) operator can be used to reverse boolean values. For example...
var falseBoolValue = false
falseBoolValue = !falseBoolValue
print(falseBoolValue)
The above code will print => "true
"
In addition to the usage as the logical NOT operator, the exclamation mark is also used to implicitly unwrap optional values. Whenever you see the exclamation mark appear at the end of an object name, such as in someVariable!
, it is being used to implicitly unwrap an optional value. Read about optionals to gain a better understanding of how !
is used with optional values.
What are '!' and '?' marks used for in Swift
The terminology used for these marks is Optional Chaining
. They are generally used for distinguishing the cases, for example, whether a property
is, a method call
returns nil
.
An example explained in Apple's language guide for Optional Chaining
is a good one to show the purpose of their use:
First, two classes called
Person
andResidence
are defined:class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
} Residence instances have a single `Int` property called `numberOfRooms`, with a default value of **1**. `Person` instances
have an optional
residence
property of typeResidence
?.If you create a new
Person
instance, itsresidence
property is
default initialized tonil
, by virtue of being optional. In the code
below,john
has aresidence
property value ofnil
:let john = Person()
If you try to access the
numberOfRooms
property of this person’s
residence
, by placing an exclamation mark afterresidence
to
force the unwrapping of its value, you trigger a runtime error,
because there is noresidence
value to unwrap:let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error
The code above succeeds when
john.residence
has a non-nil value
and will setroomCount
to anInt
value containing the appropriate
number of rooms. However, this code always triggers a runtime
error whenresidence
isnil
, as illustrated above.Optional chaining provides an alternative way to access the value of
numberOfRooms
. To use optional chaining, use a question mark in
place of the exclamation mark:if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."
This tells Swift to “chain” on the optional
residence
property
and to retrieve the value ofnumberOfRooms
ifresidence
exists.Because the attempt to access
numberOfRooms
has the potential to
fail, the optional chaining attempt returns a value of typeInt?
, or
“optional Int”. Whenresidence
isnil
, as in the example
above, this optionalInt
will also benil
, to reflect the fact
that it was not possible to accessnumberOfRooms
. The optionalInt
is accessed through optional binding to unwrap the integer and assign
the nonoptional value to theroomCount
variable.Note that this is true even though
numberOfRooms
is a nonoptional
Int
. The fact that it is queried through an optional chain means
that the call tonumberOfRooms
will always return anInt?
instead
of anInt
.You can assign a
Residence
instance tojohn.residence
, so that it
no longer has anil
value:john.residence = Residence()
Besides the general overview of Optional Chaining above, you can look at this answer in StackOverflow.
Hope this gives you some perspective on Optional Chaining.
Swift Type Inference requires question mark or exclamation point
That's not type inference. If you declare a variable's type, inference doesn't happen. Inference is all about figuring (inferring) out what a type is if you don't say explicitly.
You're having a problem with Swift initializer rules. If you declare that a class has this property:
var sut: ItemManager
Then that's non-optional, which means it must have a value by the time initialization is complete. You're not doing that, so Swift is complaining about your initializers. You can either add an init
method that assigns a value or you could declare it and assign a value at the same time-- which might look like this:
var sut: ItemManager = ItemManager()
If you declare it like this:
var sut: ItemManager?
Then it's optional, which means if you don't assign a value then it gets a value of nil. You don't have to assign a value during initialization because it already has one.
Change value to opposite with exclamation mark Swift
Because putting an exclamation mark after a variable marks force unwrapping. In general, putting the exclamation mark after an expression means forcing something (force casting with as!
or force unwrapping for optionals, etc.).
You have to put it before the value to negate a boolean expression.
(viewModel.arrValues[row] as! TestItem).isChecked = !((viewModel.arrValues[row] as? TestItem)?.isChecked)
It it okay to access an optional variable with question mark without exclamation mark?
Println()
will print the value if it has any otherwise it will print nil. Just to understand things better just try to assign value of aaa
to another string variable. It will throw error that value of optional type not unwrapped.
var aString:NSString? = "Hello"
var bString = aString // Compiler allows, as you are assigning to optional type again.
var cString:NSString = aString // Compiler throws error. You cannot assign optional type without unwrapping.
So to answer your question you need to use !
to get the value.
Edit:
var foo:Bool?
foo = false
if foo { // This always evaluates to `True`
...
}
if foo! { // This condition will now fail
...
}
The reason foo
evaluated to True
is because it was not unwrapped. Since its not unwrapped its just checking whether it has a value or not(true or false does not matter).
When foo
was unwrapped it returned a value False
hence the second if condition failed.
What is the nature of a class property when declared with = {}() in Swift?
captureSession
is lazy property but ={}()
is not regarding lazy initialization.
It is Setting a Default Property Value with a Closure or Function
. This is an example.
let titleLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.textColor = UIColor.textColor
label.font = UIFont(name: "HelveticaNeue-Medium", size: 14)
return label
}()
You can find more information at the end of this document.
Related Topics
iOS 8 Swift Audio Playback Execute Method on Completion
Linking Error When Building Parse in Xcode 7
Updated Approach to Reauthenticate a User
"Ambiguous Use of 'Children'" When Trying to Use Nstreecontroller.Arrangedobjects in Swift 3.0
How to Stop an Infinitely Rotating Image? and How Does One Implement Removeallanimations
Composing Video and Audio - Video's Audio Is Gone
Empty Class in Swift Playground Gives _Lldb_Expr_ Error
Including Zeros in Front of an Integer
After Getting Image from Uiimagepickercontroller, Uiimageview Rotates Image for iPhone 5
Is There Difference Between Using a Constructor and Using .Init
How to Run App in Simulator Xcode 6
Example for Drag and Drop Inside Nscollectionview
Swift:Program for Addition of 2 Numbers Using Closure
Xcode 7.1 Beta: Content of File Error
How to Make a Variable from a String
Checkboxes in Uitableview State Persistence
Ordering Firebase Posts Chronologically Swift
Post Requests in Alamofire Parameter Encoding Returning Get Responses