Два (или более) варианта в Swift

Во время просмотра видео Apple о отладчике LLDB я обнаружил, что я не могу найти объяснения; он говорил о необязательных значениях, когда писал:

var optional: String? = nil; //This is ok, a common optional
var twice_optional: String?? = nil; //What is this and why this useful??

Я открыл игровое поле и начал проверять его, и понял, что вы можете написать столько, сколько ?, как хотите, а затем развернуть их с тем же числом !. Я понимаю концепцию обертывания/разворачивания переменной, но не могу думать о ситуации, когда я хотел бы обернуть значение 4, 5 или 6 раз.

Ответ 1

(Обновлено для Swift> = 3)

"Double optionsals" могут быть полезны, а запись в блоге Swift "Вариант Caseases: valuesForKeys" описывает приложение.

Вот упрощенный пример:

let dict : [String : String?] = ["a" : "foo" , "b" : nil]

это словарь с необязательными строками в качестве значений. Следовательно

let val = dict[key]

имеет тип String?? aka Optional<Optional<String>>. Это .none (или nil), если ключ отсутствует в словаре, а .some(x) противном случае. Во втором случае x является String? aka Optional<String> и может быть .none (или nil) или .some(s) где s - String.

Вы можете использовать вложенную необязательную привязку для проверки различных случаев:

for key in ["a", "b", "c"] {

    let val = dict[key]
    if let x = val {
        if let s = x {
            print("\(key): \(s)")
        } else {
            print("\(key): nil")
        }
    } else {
        print("\(key): not present")
    }

}

Выход:

a: foo
b: nil
c: not present

Возможно, было бы поучительно посмотреть, как это можно добиться при сопоставлении шаблонов в switch-statement:

let val = dict[key]
switch val {
case .some(.some(let s)):
    print("\(key): \(s)")
case .some(.none):
    print("\(key): nil")
case .none:
    print("\(key): not present")
}

или, используя x? шаблон как синоним .some(x):

let val = dict[key]
switch val {
case let (s??):
    print("\(key): \(s)")
case let (s?):
    print("\(key): nil")
case nil:
    print("\(key): not present")
}

(Я не знаю разумного приложения для более глубоко вложенных опций).

Ответ 2

var tripleOptional: String???

совпадает с

var tripleOptional: Optional<Optional<Optional<String>>>

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