2015-07-17 2 views
13

Я знаю определение для одного восклицательного знака, но два?Двойное восклицание !! отметить в Свифт?

Я сегодня кодировал и компилятор «заставлял» меня добавить еще один! к моему предложению:

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

Если я использую только один! mark, проект не компилируется, что дает мне ошибку: «Значение необязательного типа« AnyObject »? не разворачивается, вы хотели использовать '!' или '?'?" Затем я добавляю еще один! и все работает.

В чем смысл восклицательные знаки в Swift?

ответ

7

В словаре вы храните AnyObject!, поэтому вы сохраняете необязательное значение. Слои слова всегда возвращают необязательное значение, которое вы храните, поэтому вы получаете необязательный вариант, поэтому вам нужно два !, чтобы развернуть его дважды.

+1

Код не «хранит AnyObject! В словаре» - индексы кода в значение типа AnyObject !. Непонятно, зачем подписываться на AnyObject! возможно, в первую очередь, но двойные необязательные варианты, вероятно, не являются ожидаемым результатом в любом API (см. мой пост ниже). –

+0

Я сегодня испытал то же самое здесь: appDelegate.window !!. RootViewController = rootNavigationController, поэтому он, похоже, не связан со словарями. – osxdirk

5

Это странный артефакт использования типа AnyObject вместо явного типа словаря. Обычно a monad like Optional (спасибо user2864740) реализует операцию связывания с сигнатурой типа Optional<T>.bind(f: T -> Optional<U>) -> Optional<U>.

Это делает так, что, когда вы получаете доступ к необязательному члену необязательного значения, вы не получаете двойной-необязательный, который вам нужно развернуть, как лук, с каждым уровнем доступа.

Если вы аналогичный пример с явным словарем, вы найдете результирующий тип, чтобы быть только один слой Дополнительно:

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) 

Это не понятно, почему это происходит с AnyObject, но я не верьте, что это намеченное поведение.

+0

Я вставил этот код в Playground, но я получаю Невозможно преобразовать значение типа [String: Int] в указанный тип AnyObject при использовании Swift 2.0. – lmiguelvargasf

+0

Это странно. Этот пример был написан на основе Swift 1.2, но я получил те же результаты с Swift 2 в Xcode 7 beta 6. –

+0

Извините, я забыл добавить 'import UIKit', я думаю, вы должны включить эту строку в начало вашего фрагмента, и было бы здорово, если вы измените 'println' на' print'. – lmiguelvargasf

Смежные вопросы