Из документации Apple :
Вы можете использовать
if
иlet
вместе работать со значениями, которые могут отсутствовать. Эти значения представлены как дополнительные. Необязательное значение либо содержит значение, либоnil
указывает, что значение отсутствует. Напишите знак вопроса (?
) после типа значения, чтобы пометить значение как необязательное.
Почему вы хотите использовать необязательное значение?
Ответы:
Необязательным в Swift является тип, который может содержать либо значение, либо отсутствие значения. Необязательные написаны добавлением
?
к любому типу:Необязательные (вместе с Generics) являются одной из самых сложных концепций Swift для понимания. Из-за того, как они написаны и используются, легко понять, что они из себя представляют. Сравните необязательное выше с созданием обычной строки:
Из синтаксиса это выглядит как необязательная строка очень похожа на обычную строку. Это не. Необязательная строка не является строкой с включенной «необязательной» настройкой. Это не особая разновидность String. Строка и необязательная строка - это совершенно разные типы.
Вот самая важная вещь, которую нужно знать: необязательный - это своего рода контейнер. Необязательная строка - это контейнер, который может содержать строку. Необязательный Int - это контейнер, который может содержать Int. Думайте о дополнительной как своего рода посылка. Прежде чем открыть его (или «развернуть» на языке опций), вы не узнаете, содержит ли он что-то или ничего.
Вы можете увидеть, как дополнительные функции реализованы в стандартной библиотеке Swift, введя «Optional» в любой файл Swift и нажав ⌘ по нему. Вот важная часть определения:
Необязательно, это просто
enum
один из двух случаев:.none
или.some
. Если это.some
, есть связанное значение, которое в приведенном выше примере будетString
«Hello». Необязательный параметр использует Generics для задания типа связанного значения. Тип необязательной строки не являетсяString
, этоOptional
или, точнееOptional<String>
.Все, что Swift делает с опциями, является магией, чтобы сделать чтение и написание кода более свободным. К сожалению, это затеняет то, как это на самом деле работает. Я пойду через некоторые трюки позже.
Примечание: я буду много говорить о необязательных переменных, но также неплохо создавать дополнительные константы. Я помечаю все переменные их типом, чтобы было легче понять создаваемые типы типов, но вам не нужно это делать в своем собственном коде.
Как создать опцию
Чтобы создать необязательный, добавьте
?
после того типа, который вы хотите обернуть. Любой тип может быть необязательным, даже ваши собственные типы. Вы не можете иметь пробел между типом и?
.Использование опций
Вы можете сравнить необязательный параметр с,
nil
чтобы увидеть, имеет ли он значение:Это немного сбивает с толку. Это подразумевает, что необязательным является либо одно, либо другое. Это либо ноль, либо «Боб». Это не правда, необязательное не превращается во что-то еще. Сравнение его с nil - это трюк, чтобы сделать код более простым для чтения. Если необязательный параметр равен нулю, это просто означает, что перечисление в настоящее время установлено на
.none
.Только опционально может быть ноль
Если вы попытаетесь установить для необязательной переменной значение nil, вы получите ошибку.
Другой способ взглянуть на опциональные возможности - это дополнение к обычным переменным Swift. Они являются аналогом переменной, которая гарантированно имеет значение. Свифт - это осторожный язык, который ненавидит двусмысленность. Большинство переменных определены как необязательные, но иногда это невозможно. Например, представьте контроллер представления, который загружает изображение либо из кэша, либо из сети. Это может иметь или не иметь это изображение во время создания контроллера представления. Нет способа гарантировать значение для переменной изображения. В этом случае вам придется сделать это необязательно. Он начинается как
nil
и когда изображение извлекается, необязательный получает значение.Использование опционально раскрывает намерение программистов. По сравнению с Objective-C, где любой объект может быть нулевым, Swift требует от вас четкого представления о том, когда значение может отсутствовать и когда оно гарантированно существует.
Чтобы использовать необязательно, вы "разверните" его
Дополнительный
String
не может использоваться вместо фактическогоString
. Чтобы использовать упакованное значение внутри необязательного, вы должны развернуть его. Самый простой способ развернуть необязательное - добавить!
после имени необязательного. Это называется «распаковка силы». Он возвращает значение внутри необязательного (как исходный тип), но если необязательныйnil
, это вызывает сбой во время выполнения. Перед развертыванием вы должны быть уверены, что есть значение.Проверка и использование дополнительного
Поскольку вы всегда должны проверять nil перед развертыванием и использованием необязательного, это распространенный шаблон:
В этом шаблоне вы проверяете наличие значения, а затем, когда вы уверены, что оно есть, вы принудительно распаковываете его во временную константу. Так как это обычное дело, Swift предлагает ярлык с использованием «если позволено». Это называется «необязательное связывание».
Это создает временную константу (или переменную , если заменить
let
сvar
), областью действия которого только в пределах , если это брекеты - х. Поскольку использование имени, такого как «unwrappedMealPreference» или «realMealPreference», является бременем, Swift позволяет вам повторно использовать исходное имя переменной, создавая временное имя в области видимости скобокВот код, демонстрирующий использование другой переменной:
Необязательное связывание работает, проверяя, равняется ли необязательное ноль. Если это не так, он разворачивает необязательное значение в предоставленную константу и выполняет блок. В Xcode 8.3 и позже (Swift 3.1), попытка напечатать необязательный как это вызовет бесполезное предупреждение. Используйте дополнительные,
debugDescription
чтобы заставить его замолчать:Для чего нужны опции?
Опциональные варианты имеют два варианта использования:
Некоторые конкретные примеры:
middleName
илиspouse
вPerson
классеweak
свойств в классах. То, на что они указывают, может быть установленоnil
в любое времяBoolean
Необязательные в Objective-C не существуют, но существует эквивалентная концепция, возвращающая ноль. Методы, которые могут вернуть объект, могут вернуть nil. Это означает «отсутствие действительного объекта» и часто используется, чтобы сказать, что что-то пошло не так. Он работает только с объектами Objective-C, но не с примитивами или базовыми C-типами (перечисления, структуры). Objective-C часто специализировался типами представляет отсутствие этих значений (
NSNotFound
которая на самом делеNSIntegerMax
,kCLLocationCoordinate2DInvalid
представляет недопустимые координаты,-1
или какое - либо отрицательное значение также используется). Кодировщик должен знать об этих специальных значениях, поэтому они должны быть задокументированы и изучены для каждого случая. Если метод не может бытьnil
принят в качестве параметра, это должно быть задокументировано. В Objective-C,nil
был указателем так же, как все объекты были определены как указатели, ноnil
указывали на определенный (нулевой) адрес. В Swiftnil
это литерал, который означает отсутствие определенного типа.По сравнению с
nil
Раньше вы могли использовать любой дополнительный как
Boolean
:В более поздних версиях Swift вы должны использовать
leatherTrim != nil
. Почему это? Проблема в том, что aBoolean
может быть обернут в необязательный. Если у вас естьBoolean
такие:у него есть два типа «ложь», один, где нет значения, и другой, где он имеет значение, но значение равно
false
. Свифт ненавидит двусмысленность, поэтому теперь вы всегда должны проверять опцию противnil
.Вы можете спросить, в чем смысл необязательного
Boolean
? Как и в случае других опций,.none
состояние может указывать, что значение пока неизвестно. На другом конце сетевого вызова может быть что-то, что требует некоторого времени для опроса. Необязательные логические значения также называются « трехзначными логическими значениями »Быстрые трюки
Swift использует некоторые приемы, чтобы опциональные опции работали. Рассмотрим эти три строки обычного вида дополнительного кода;
Ни одна из этих строк не должна компилироваться.
String
разные типыЯ рассмотрю некоторые детали реализации опций, которые позволяют этим линиям работать.
Создание необязательного
Использование
?
для создания необязательного синтаксического сахара, разрешено компилятором Swift. Если вы хотите сделать это долгий путь, вы можете создать необязательный, как это:Это вызывает
Optional
первый инициализатор,public init(_ some: Wrapped)
который выводит тип, связанный с необязательным, из типа, используемого в скобках.Еще более длинный способ создания и настройки необязательного:
Установка необязательного к
nil
Вы можете создать необязательное без начального значения или создать с начальным значением
nil
(оба имеют одинаковый результат).Разрешение равных опциональных параметров
nil
разрешено протоколомExpressibleByNilLiteral
(ранее названнымNilLiteralConvertible
). Необязательный создается соOptional
вторым инициализаторомpublic init(nilLiteral: ())
. Документы говорят, что вы не должны использоватьExpressibleByNilLiteral
ничего, кроме опциональных, так как это изменило бы значение nil в вашем коде, но это возможно сделать:Тот же протокол позволяет установить уже созданный необязательный параметр
nil
. Хотя это не рекомендуется, вы можете напрямую использовать инициализатор литералов nil:Сравнивая необязательный к
nil
Необязательные определяют два специальных оператора "==" и "! =", Которые вы можете увидеть в
Optional
определении. Первый==
позволяет вам проверить, равен ли любой необязательный параметр нулю. Два разных дополнительных параметра, которые установлены в .none, всегда будут равны, если связанные типы одинаковы. Когда вы сравниваете с nil, за кулисами Swift создает необязательный тип того же связанного типа, для которого установлено значение .none, а затем использует его для сравнения.Второй
==
оператор позволяет сравнить два варианта. Оба должны быть одного типа, и этот тип должен соответствоватьEquatable
(протокол, который позволяет сравнивать вещи с помощью обычного оператора "=="). Swift (предположительно) разворачивает два значения и сравнивает их напрямую. Он также обрабатывает случай, когда один или оба из дополнительных опций.none
. Обратите внимание на различие между сравнением сnil
буквальным.Кроме того, он позволяет сравнивать любой
Equatable
тип с необязательной упаковкой этого типа:За кулисами Swift оборачивает необязательное как необязательное перед сравнением. Он работает и с литералами (
if 23 == numberFromString {
)Я сказал, что есть два
==
оператора, но на самом деле есть третий, который позволяет поместитьnil
в левую часть сравненияНейминг Опционально
Не существует соглашения Swift для именования необязательных типов, отличных от необязательных типов. Люди избегают добавлять что-либо к имени, чтобы показать, что это необязательный параметр (например, «AdditionalMiddleName» или «возможный номер_строки»), и позволяют объявлению показать, что это необязательный тип. Это становится трудным, когда вы хотите назвать что-то для хранения значения из необязательного. Название «middleName» подразумевает, что это тип String, поэтому, когда вы извлекаете из него значение String, вы часто можете получить такие имена, как «actualMiddleName» или «unwrappedMiddleName» или «realMiddleName». Используйте необязательное связывание и повторно используйте имя переменной, чтобы обойти это.
Официальное определение
Из «Основы» на языке программирования Swift :
Чтобы закончить, вот стихотворение 1899 года об опциях:
Вчера на лестнице
я встретил человека, которого там
не было. Сегодня его не было снова.
Мне бы хотелось, чтобы он ушел.
Антигонист
Больше ресурсов:
источник
if myString
больше не компилируется Вам нужноif myString != nil
. Смотрите документацию .Давайте возьмем пример:
NSError
если нет возвращаемой ошибки, вы можете сделать необязательным возвращение Nil. Нет смысла присваивать ему значение, если нет ошибки ..Это также позволяет вам иметь значение по умолчанию. Таким образом, вы можете установить для метода значение по умолчанию, если функции ничего не передано
источник
func isNil<T>(t: T?) -> Bool { return t == nil }
вернется,true
даже еслиnil
в выражении есть необязательное значение .return x == 5
? Что такого особенного в 5?Вы не можете иметь переменную, на которую указывает
nil
Swift - там нет указателей и нулевых указателей. Но в API вы часто хотите иметь возможность указывать либо определенный тип значения, либо отсутствие значения - например, есть ли в моем окне делегат, и если да, то кто это? Опционально это безопасный для Swift тип памяти и способ памяти.источник
Я сделал короткий ответ, который подводит итог большей части вышесказанного, чтобы очистить неопределенность, которая была в моей голове как новичка:
В отличие от Objective-C, ни одна переменная не может содержать nil в Swift, поэтому был добавлен необязательный тип переменной (переменные с суффиксом «?»):
Большая разница в том, что дополнительные переменные не хранят значения напрямую (как обычные переменные Obj-C), они содержат два состояния : « имеет значение » или « имеет ноль »:
Таким образом, вы можете проверить эти переменные в разных ситуациях:
Используя "!" суффикс, вы также можете получить доступ к значениям, заключенным в них, только если они существуют . (т.е. это не ноль ):
Вот почему вам нужно использовать "?" и "!" и не использовать их все по умолчанию. (это было мое самое большое недоумение)
Я также согласен с ответом выше: необязательный тип не может использоваться как логическое значение .
источник
В целевых C переменные без значения были равны 'nil' (также можно было использовать значения 'nil', такие же, как 0 и false), следовательно, было возможно использовать переменные в условных выражениях (переменные, имеющие значения такие же, как 'TRUE) 'и те, у которых нет значений, были равны' ЛОЖЬ ').
Swift обеспечивает безопасность типов, предоставляя «дополнительное значение». т.е. предотвращает возникновение ошибок при назначении переменных разных типов.
Таким образом, в Swift только условные выражения могут содержать только логические значения.
Здесь, даже несмотря на то, что «hw» является строкой, ее нельзя использовать в операторе if, как в цели C.
Для этого это должно быть создано как,
источник
Необязательное значение позволяет показать отсутствие значения. Немного похоже на NULL в SQL или NSNull в Objective-C. Я думаю, это будет улучшение, поскольку вы можете использовать это даже для «примитивных» типов.
Выдержка из: Apple Inc. «Язык программирования Swift». интерактивные книги. https://itun.es/gb/jEUH0.l
источник
nil
просто синтаксический сахар для константы enumOptionalValue<T>.None
(гдеT
тип соответствует контексту, в котором вы используетеnil
).?
это ярлык дляOptionalValue<T>.Some(T)
.Необязательный означает, что Swift не совсем уверен, соответствует ли значение типу: например, Int? означает, что Swift не совсем уверен, является ли число Int.
1) Если вы абсолютно уверены в типе, вы можете использовать восклицательный знак, чтобы принудительно развернуть его, например:
Если вы принудительно распакуете необязательное значение, равное нулю, вы можете столкнуться с этой ошибкой сбоя:
Это не обязательно безопасно, поэтому вот метод, который может предотвратить сбой, если вы не уверены в типе и значении:
2) Неявно развернутый необязательный
3) Охранное заявление
Отсюда вы можете пойти дальше и использовать переменную unwrapped. Удостоверьтесь, что принудительно разверните (с!), Если вы уверены в типе переменной.
источник
Когда я начал учиться,
Swift
было очень трудно понять, почему необязательно .Давайте думать так. Давайте рассмотрим класс,
Person
который имеет два свойстваname
иcompany
.Теперь давайте создадим несколько объектов
Person
Но мы не можем перейти
Nil
кname
Теперь поговорим о том, почему мы используем
optional?
. Давайте рассмотрим ситуацию, когда мы хотим добавитьInc
после названия компании, какapple
будетapple Inc
. Нам нужно добавитьInc
после названия компании и распечатать.Теперь давайте изучим, почему необязательный имеет место.
Позволяет заменить
bob
наtom
И поздравляю! мы имеем дело с
optional?
Таким образом, точки реализации
nil
nil
.Спасибо ... Счастливого кодирования
источник
Давайте поэкспериментируем с нижеследующим кодом Playground. Надеюсь, уясним, что является необязательным, и причину его использования.
источник
Из https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :
Чтобы понять глубже, прочитайте ссылку выше.
источник
Хорошо...
Основное отличие состоит в том, что необязательное связывание завершается неудачно, когда необязательное значение равно nil, тогда как принудительное развертывание вызывает ошибку времени выполнения, когда необязательное значение равно nil.
Чтобы отразить тот факт, что необязательное сцепление может быть вызвано для значения nil, результатом необязательного вызова цепочки всегда является необязательное значение, даже если запрашиваемое свойство, метод или индекс, возвращают неопциональное значение. Это необязательное возвращаемое значение можно использовать, чтобы проверить, был ли необязательный вызов цепочки успешным (возвращаемая необязательная содержит значение) или не удалась из-за значения nil в цепочке (возвращаемое необязательное значение равно nil).
В частности, результат необязательного вызова цепочки имеет тот же тип, что и ожидаемое возвращаемое значение, но заключен в необязательный. Свойство, которое обычно возвращает Int, будет возвращать Int? при доступе через необязательную цепочку.
Вот базовое учебное пособие от Apple Developer Committee: Необязательная цепочка
источник
Необязательным в Swift является тип, который может содержать либо значение, либо отсутствие значения. Факультативные написаны добавлением ? к любому типу:
Вы можете обратиться к этой ссылке, чтобы получить глубокие знания: https://medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870
источник
Вот эквивалентное необязательное объявление в Swift:
Это объявление создает переменную с именем middleName типа String. Знак вопроса (?) После типа переменной String указывает, что переменная middleName может содержать значение, которое может быть либо String, либо nil. Любой, кто смотрит на этот код, сразу же знает, что middleName может быть нулевым. Это самодокументирование!
Если вы не укажете начальное значение для необязательной константы или переменной (как показано выше), для вас автоматически будет установлено значение nil. Если вы предпочитаете, вы можете явно установить начальное значение равным nil:
для более подробной информации для дополнительной читайте ссылку ниже
http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values
источник