What Does an Exclamation Mark in a Property in Swift Language

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 from john.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 the Person value if it exists, runtime error if it is nil)
  • "optional binding": if let p = john { println(p) } (executes the println 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 and Residence 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 type Residence?.

If you create a new Person instance, its residence property is
default initialized to nil, by virtue of being optional. In the code
below, john has a residence property value of nil:

let john = Person()

If you try to access the numberOfRooms property of this person’s
residence, by placing an exclamation mark after residence to
force the unwrapping of its value, you trigger a runtime error,
because there is no residence 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 set roomCount to an Int value containing the appropriate
number of rooms. However, this code always triggers a runtime
error
when residence is nil, 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 of numberOfRooms if residence exists.

Because the attempt to access numberOfRooms has the potential to
fail, the optional chaining attempt returns a value of type Int?, or
optional Int”. When residence is nil, as in the example
above, this optional Int will also be nil, to reflect the fact
that it was not possible to access numberOfRooms. The optional Int
is accessed through optional binding to unwrap the integer and assign
the nonoptional value to the roomCount 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 to numberOfRooms will always return an Int? instead
of an Int.

You can assign a Residence instance to john.residence, so that it
no longer has a nil 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



Leave a reply



Submit