Double exclamation !! mark in Swift?
Asked Answered
B

2

18

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?

Bostick answered 17/7, 2015 at 2:22 Comment(0)
J
9

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.

Jehial answered 17/7, 2015 at 2:31 Comment(2)
The code does not "store an AnyObject! in the dictionary"-- the code subscripts into a value of type AnyObject!. It's not clear why subscripting into an AnyObject! is possible in the first place, but double optionals are probably not an intended outcome in any API (see my post below).Perbunan
I today experienced the same here: appDelegate.window!!.rootViewController = rootNavigationController so it does not seem to be related to dictionaries.Swart
P
7

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.

Perbunan answered 17/7, 2015 at 3:58 Comment(3)
I have pasted this code in the Playground, but I am getting Cannot convert value of type [String: Int] to specified type AnyObject, when using Swift 2.0.Nanine
That's strange. This example was written based on Swift 1.2, but I got the same results with Swift 2 in Xcode 7 beta 6.Perbunan
Sorry, I forgot to add import UIKit, I guess you should include this line at the beginning of your snippet, and it would be great if you change println to print.Nanine

© 2022 - 2024 — McMap. All rights reserved.