Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double exclamation !! mark in Swift?

I know the definition for a single exclamation mark, but two?

I was coding today and the compiler "force" me to add one more ! to my sentence:

mySignal.subscribeNext({
        (value: AnyObject!) -> () in
        let list: RACSequence = value["myObject"]!!.rac_sequence
        ...

If I use only one ! mark, the project doesn't compile, giving me the error: "Value of optional type 'AnyObject?' not unwrapped; did you mean to use '!' or '?'?" Then I add one more ! and everything works.

What's the meaning for two exclamation marks in Swift?

like image 798
FelipeDev.- Avatar asked Jul 17 '15 02:07

FelipeDev.-


People also ask

What does the exclamation mark mean in Swift?

Swift uses exclamation marks to signal both force unwrapping of optionals and explicitly unwrapped optionals.

What does double question mark mean in Swift?

Double question mark is a nil-coalescing operator. In plain terms, it is just a shorthand for saying != nil . First it checks if the the return value is nil, if it is indeed nil, then the left value is presented, and if it is nil then the right value is presented.

What does the double exclamation point mean?

This punctation emoji of a double exclamation mark features two big red exclamation points that can be used to express surprise, shock, or to really emphasize or drive home a point. This emoji packs a punch and is also reminiscent of comic book actions. Wham!

What are the question marks and an exclamation mark in Swift?

An implicitly unwrapped optional is defined with an exclamation mark instead of a question mark. The exclamation mark indicates that the name property of the Person class is defined as an implicitly unwrapped optional. Note that the print statement returns the value of name , not an optional.


2 Answers

You're storing an AnyObject! in the dictionary, so you're storing an optional as the value. Dictionary subscripts always return an optional of the value you're storing, so you're getting an optional optional, which is why you need two !, to unwrap it twice.

like image 145
Dave Wood Avatar answered Oct 20 '22 20:10

Dave Wood


This is a strange artifact of the use of the AnyObject type instead of an explicit dictionary type. Normally, a monad like Optional (thanks user2864740) implements a bind operation with a signature like Optional<T>.bind(f: T -> Optional<U>) -> Optional<U>.

This makes it so when you access an optional member of an optional value, you don't get a double-optional that you have to unwrap like an onion with each layer of access.

If you do a similar example with an explicit dictionary, you'll find the resulting type to be just a single layer of Optional:

import UIKit

let anyDict: AnyObject? = ["foo" : 34, "bar" : 13]
let anyElement = anyDict?["foo"]
print(anyElement) // Optional(Optional(34))

let dict: [String : Int]? = ["foo" : 34, "bar" : 13]
let element = dict?["foo"]
print(element) // Optional(34)

It's not clear why this is happening with AnyObject, but I don't believe it's the intended behavior.

like image 39
Rikki Gibson Avatar answered Oct 20 '22 18:10

Rikki Gibson