2015-07-17 22 views
13

Znam definicję jednego wykrzyknika, ale dwa?Podwójny wykrzyknik !! znak w Swift?

Kodowałem dzisiaj, a kompilator "zmusił" mnie do dodania jeszcze jednego! do mojego zdania:

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

Jeśli używam tylko jednego! mark, projekt się nie kompiluje, dając mi błąd: "Wartość opcjonalnego typu" AnyObject? " nieopakowany, czy chciałeś użyć "!" lub "?"? " Potem dodaję jeszcze jeden! i wszystko działa.

Co oznacza dla dwa wykrzykniki w Swift?

Odpowiedz

7

Przechowujesz w słowniku słownik AnyObject!, więc jako wartość przechowujesz opcjonalne. Subskrypcje słownika zawsze zwracają opcjonalną wartość, którą przechowujesz, więc dostajesz opcjonalny opcjonalny, dlatego potrzebujesz dwóch !, aby go dwukrotnie rozwinąć.

+1

Kod nie "przechowuje AnyObject!" W słowniku "- kod dolny do wartości typu AnyObject !. Nie jest jasne, dlaczego subskrybowanie do AnyObject! jest możliwe w pierwszej kolejności, ale podwójne opcje prawdopodobnie nie są zamierzonym wynikiem w żadnym interfejsie API (zobacz mój wpis poniżej). –

+0

Dzisiaj doświadczyłem tego samego: appDelegate.window !!. RootViewController = rootNavigationController, więc nie wydaje się być związany ze słownikami. – osxdirk

5

Jest to dziwny artefakt dotyczący użycia typu AnyObject zamiast wyraźnego typu słownika. Normalnie, a monad like Optional (dzięki user2864740) implementuje operację wiązania z sygnaturą podobną do Optional<T>.bind(f: T -> Optional<U>) -> Optional<U>.

Powoduje to, że gdy uzyskujesz dostęp do opcjonalnego elementu opcjonalnej wartości, nie dostajesz podwójnego opcjonalnego, który musisz rozwinąć jak cebulkę z każdą warstwą dostępu.

Jeśli zrobisz podobny przykład z wyraźną słowniku znajdziesz wynikowy typ być tylko jedna warstwa Opcjonalnie:

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) 

Nie jest jasne, dlaczego tak się dzieje z AnyObject, ale nie wierz, że to zamierzone zachowanie.

+0

Wkleiłem ten kod w Playground, ale otrzymuję Nie mogę przekonwertować wartości typu [String: Int] na określony typ AnyObject, gdy używam Swift 2.0. – lmiguelvargasf

+0

To dziwne. Ten przykład został napisany w oparciu o Swift 1.2, ale mam takie same wyniki z Swift 2 w Xcode 7 beta 6. –

+0

Przepraszamy, zapomniałem dodać 'import UIKit', myślę że powinieneś dołączyć tę linię na początku twojego fragmentu, i byłoby wspaniale, gdybyś zmieniła 'println' na' print'. – lmiguelvargasf