Константы и переменные любого типа данных в языке программирования Swift (строкового, целочисленного, числового с плавающей точкой, логического и так далее) всегда имеют некое непустое значение. Это относится также к переменным, хранящим ссылки на объекты классов: даже в этом случае переменная не может содержать никакой ссылки, она всегда указывает на какой-либо объект. (Это очень принципиальное отличие, например, от языка программирования C#, где все ссылочные переменные могут быть пустыми, то есть равными nil.)

Однако в процессе написания программы часто возникает необходимость указать для переменной именно отсутствие какого-либо значения вовсе. Для этого при программировании в Swift существуют опционалы.

Опционал (другими словами, опциональный тип данных) предоставляет собой определение переменной, реализующее следующие две возможности: переменная-опционал может содержать значение некоего определенного типа данных, называемого в дальнейшем базовым, либо не содержать ничего вообще. Для того чтобы показать отсутствие значение у переменной-опционала, нужно присвоить ей особое значение nil.

Итак, в общем виде определяется опционал следующим образом:
Optional<Type> (полный вариант записи опционала) или Type! (краткий вариант записи), где Type — базовый тип.

Например:
var x: Optional<Int>
var y: Int?

Оба варианта записи означают, что переменные x и y могут содержать целое число или не содержать ничего (быть равными nil). Также следует отметить, что оба варианта записи создадут переменные одинакового типа (то есть в дальнейшем запись x = y не вызовет ошибки несоответствия типов данных).
(Проводя дальнейшее сравнение с программированием в C#, опционал в Swift — это, по сути, обычный ссылочный тип данных в C#. Например, String? языка Swift аналогичен обычному String в C#).

Важно: при программировании на Swift при объявления переменной-опционала необходимо явно указать ее опциональный тип:

var s: String? = «строка-опционал»

(В случае записи var s = «строка» будет создана переменная обычного типа String. В случае записи var s = nil компилятором будет выдана ошибка «‘nil’ requires a contextual type» — nil требует контекстного типа).

При работе с опционалами нельзя выполнять операции непосредственно между переменными опционального и базового типа. Это приведет к ошибке во время компиляции. Пример:

var x1: Int = 111
var x2: Int? = 222

Выполнение выражения x1 + x2 вызовет ошибку «Value of optional type Int? must be unwrapped to value Int» (значение опционала должно быть распаковано). Иными словами, значение переменной-опционала должно быть неким образом преобразовано к базовому типу.

При программировании на Swift существует несколько таких механизмов преобразования опционала к базовому типу:
• force unwrapping;
• implicity unwrapping;
• optional bunding;
• nil coalescing.

Механизм force unwrapping

Механизм force unwrapping (принудительная распаковка) явно преобразует опционал в значение базового типа путем добавления восклицательного знака после имени переменной-опционала.

Например:
var x1: Int = 10
var x2: Int? = 20
var x3 = x1 + x2!

При таком способе получения значения опционала, содержащее nil, возникает ошибка во время выполнения программы.

var i: Int? = nil

Выполнение выражения i! приведет к ошибке при выполнении программы «Unexpectedly found nil while unwrapping an optional value» (Неожиданное обнаружение nil во время распаковки значения опционала).

При использовании механизма force unwrapping для получения значения переменной-опционала необходимо быть уверенным, что опционал имеет непустое значение. Для выполнения такой проверки используется условный оператор и операторы сравнения опционала с nil (равенства «==» и неравенства «!=»).

Например:
let x1: Int = 333
let x2: Int? = 444
if x2 != nil {let x3 = x1 + x2!}

Механизм implicity unwrapping

Другим вариантом извлечения значения переменной-опционала является механизм implicity unwrapping (неявного извлечения).

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

Именно в таких случаях используется механизм implicity unwrapping. Для этого при инициализации опционала знак вопроса (?) заменяется на знак восклицания (!).

let str1: String! = «implicity unwrapping»
let str2: String? = «optional string»
let str3: String! = str2! // другой вариант неявной распаковки опционала

Механизм optional binding

Механизм optinal binding (связывание опционала) используется для определения наличия в опционала непустого значения и, в случае если это так, получения значение опционала во временную переменную или константу.

В общем виде механизм optional binding выглядит следующим образом:
if let временная переменная = опционал { //действия для непустого опционала }
else { // действия для пустого опционала}

В случае, если опционал содержит непустое значение, создается временная переменная (или константа), в которую будет записано распакованное значение опционала, и выполнены действия тела условного оператора (значение опционала доступно через созданную временную переменную (константу), имеющую базовый тип; также необходимо отметить, что, учитывая правила определения области видимости переменных и констант в Swift, временная переменная будет доступна только в блоке действия для непустого опционала).

В противном случае, когда значение опционала не может быть извлечен (равен nil) — выполняется блок else. Блок else может отсутствовать.

var x1: Int = 100
var x2: Int? = 200
if let x_temp = x2 { let x3 = x1 + x_temp }

Механизм nil coalescing

Еще одним вариантом распаковки опционала является механизм nil coalescing (соединения с nil) с использованием оператора ??.
В общим виде такой способ выглядит следующим образом:
let переменная = опционал ?? значениепоумолчанию

В случае, когда опционал не равен nil, его значение записывается в переменную, в противном случае в переменную записывается значение по умолчанию, расположенное справа от оператора ??.

В примере приведенный механизм реализуется следующим образом:
let x1: Int = 1
let x2: Int? = 2
let temp = x2 ?? 0
let x3 = x1 + temp

Наиболее безопасными и поэтому рекомендуемыми механизмами работы с опционалами являются optional binding и nil coalescing.


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