Я изучаю Swift для iOS 8 / OSX 10.10, следуя этому руководству , и термин « развернутое значение » используется несколько раз, как в этом параграфе (в разделе « Объекты и класс» ):
При работе с дополнительными значениями вы можете написать? перед операциями, такими как методы, свойства и подписка. Если значение до? ноль, все после? игнорируется и значение всего выражения равно нулю. В противном случае необязательное значение разворачивается , и все после? действует на развернутую стоимость . В обоих случаях значение всего выражения является необязательным значением.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
Я не понимаю, и искал в Интернете без удачи.
Что это значит?
редактировать
Из ответа Цезария есть небольшая разница между выводом исходного кода и окончательным решением (проверено на игровой площадке):
Оригинальный код
Решение Цезари
Свойства суперкласса отображаются в выходных данных во втором случае, тогда как в первом случае есть пустой объект.
Разве результат не должен быть одинаковым в обоих случаях?
Связанные вопросы и ответы: Что такое необязательное значение в Swift?
Ответы:
Во-первых, вы должны понять, что такое необязательный тип. Необязательный тип в основном означает, что переменная может быть
nil
.Пример:
Знак вопроса указывает на то, что
canBeNil
может бытьnil
.Это не будет работать:
Чтобы получить значение из вашей переменной, если оно не является обязательным, вы должны развернуть его . Это просто значит поставить восклицательный знак в конце.
Ваш код должен выглядеть так:
Sidenote:
Вы также можете объявить необязательные варианты автоматического развертывания, используя восклицательный знак вместо знака вопроса.
Пример:
Итак, альтернативный способ исправить ваш код:
РЕДАКТИРОВАТЬ:
Разница, которую вы видите, является как раз признаком того факта, что необязательное значение обернуто . Существует еще один слой поверх него. Развернутая версия только показывает прямой объект , потому что, ну, развернутая.
Быстрое сравнение детской площадки:
В первом и втором случаях объект не разворачивается автоматически, поэтому вы видите два «layer» (
{{...}}
), тогда как в третьем случае вы видите только один layer ({...}
), потому что объект автоматически разворачивается.Разница между первым и вторым двумя случаями заключается в том, что вторые два случая приведут к ошибке времени выполнения, если
optionalSquare
задано значениеnil
. Используя синтаксис в первом случае, вы можете сделать что-то вроде этого:источник
init()
функции класса. Я рекомендую прочитать главы «Основы» (опциональные обложки), «Инициализация» и «Опциональная цепочка» в книге Swift, выпущенной Apple.Существующий правильный ответ великолепен, но я обнаружил, что для полного понимания этого мне нужна хорошая аналогия, поскольку это очень абстрактная и странная концепция.
Итак, позвольте мне помочь тем коллегам-разработчикам «правильного мышления» (визуального мышления), предоставив другую точку зрения в дополнение к правильному ответу. Вот хорошая аналогия, которая мне очень помогла.
Подарочная упаковка
Думайте об опциях как о подарках на день рождения, которые идут в жесткой, твердой, цветной упаковке.
Вы не знаете, есть ли что-нибудь внутри упаковки, пока не развернете подарок - может быть, внутри ничего нет! Если внутри что-то есть, это может быть еще один подарок, который также обернут, и который также может не содержать ничего . Вы могли бы даже развернуть 100 вложенных подарков, чтобы наконец обнаружить, что нет ничего, кроме упаковки .
Если значение необязательное - нет
nil
, теперь вы обнаружили поле, содержащее что-то . Но, особенно если значение не является явно типизированным и является переменной, а не предопределенной константой, вам все равно может потребоваться открыть окно, прежде чем вы сможете узнать что-то конкретное о том, что находится в блоке, например, какой это тип или какой фактическое значение есть.Что в коробке?! аналогия
Даже после того, как вы развернули переменную, вы все равно похожи на Брэда Питта в последней сцене в SE7EN ( предупреждение : спойлеры и ненормативная лексика и насилие с очень высокой оценкой R), потому что даже после того, как вы развернули настоящее, вы попадаете в следующую ситуацию: теперь у вас есть
nil
, или коробка, содержащая что-то (но вы не знаете, что).Вы можете знать тип чего-то . Например, если вы объявили переменную как тип,
[Int:Any?]
то вы бы знали, что у вас есть (потенциально пустой) словарь с целочисленными индексами, которые дают упакованное содержимое любого старого типа.Вот почему работа с типами коллекций (словарями и массивами) в Swift может быть довольно сложной.
Дело в точке:
источник
Swift высоко ценит безопасность типов. Весь язык Swift был разработан с учетом безопасности. Это одна из отличительных черт Swift, которую стоит приветствовать с распростертыми объятиями. Это поможет в разработке чистого, читабельного кода и поможет предотвратить сбой вашего приложения.
Все опции в Swift обозначены
?
символом. Устанавливая?
после имени типа , в котором вы объявляя в качестве факультативных вы по существу литье это не как тип , в котором находится на рассмотрении?
, но вместо этого в качестве дополнительного типа.Использование опционально
Это не значит, что вы работаете с типом
String
. Это означает, что вы работаете с типомString?
(String Optional или Optional String). На самом деле, когда вы пытаетесьво время выполнения консоль отладки напечатает
Optional("foobar")
. Часть «Optional()
» указывает, что эта переменная может иметь или не иметь значение во время выполнения, но именно так и происходит в настоящее время со строкой «foobar». Эта «Optional()
» индикация останется, если вы не сделаете то, что называется «развертывание» необязательного значения.Развертывание необязательного означает, что вы используете этот тип как необязательный. Это создаст новый тип и присвоит значение, которое находилось в этом необязательном, новому необязательному типу. Таким образом, вы можете выполнять операции с этой переменной, поскольку компилятор гарантированно имеет твердое значение.
Условно Unwrapping проверит, является ли значение в дополнительном
nil
или нет. Если это не такnil
, будет вновь созданная константная переменная, которой будет присвоено значение и развернута в необязательную константу. И оттуда вы можете смело использовать необязательные вif
блоке.Условное развёртывание опций - это самый чистый способ получить доступ к значению опциона, потому что если оно содержит значение nil, то все в блоке if let не будет выполняться. Конечно, как любое выражение if, вы можете включить блок else
Принудительная распаковка выполняется с помощью так называемого
!
("взрыва") оператора. Это менее безопасно, но все же позволяет вашему коду компилироваться. Однако всякий раз, когда вы используете оператор bang, вы должны быть уверены на 1000%, что ваша переменная действительно содержит твердое значение перед принудительным развертыванием.Это выше полностью действительный код Swift. Он печатает значение,
myString
которое было установлено как «foobar». Пользователь увидитfoobar
напечатанное в консоли и все. Но давайте предположим, что значение никогда не было установлено:Теперь у нас другая ситуация в наших руках. В отличие от Objective-C, всякий раз, когда делается попытка принудительно развернуть необязательный параметр, и необязательный параметр не был установлен, и
nil
при попытке развернуть необязательный элемент, чтобы увидеть, что внутри вашего приложения, будет аварийно завершать работу.Развертывание с типом литья . Как мы уже говорили ранее, хотя вы
unwrapping
необязательный, вы на самом деле приводите к не необязательному типу, вы также можете привести не необязательный тип к другому типу. Например:Где-то в нашем коде переменная
something
будет установлена с некоторым значением. Может быть, мы используем дженерики или, может быть, есть какая-то другая логика, которая заставит это измениться. Итак, позже в нашем коде мы хотим использовать,something
но все равно сможем обрабатывать его по-разному, если это другой тип. В этом случае вы захотите использоватьas
ключевое слово, чтобы определить это:Обратите внимание на разницу между двумя
as
ключевыми словами. Как и раньше, когда мы принудительно разворачивали опциональный файл, мы использовали для этого!
оператор bang. Здесь вы будете делать то же самое, но вместо того, чтобы разыгрывать как необязательное, вы также разыгрываете егоInt
. И он должен быть в состоянии быть пониженным, какInt
, в противном случае, как при использовании оператора взрыва, когда значениеnil
вашего приложения потерпит крах.И для того, чтобы использовать эти переменные вообще в некоторой сортировке или математической операции, они должны быть развернуты, чтобы сделать это.
Например, в Swift только допустимые числовые типы данных одного типа могут работать друг с другом. Когда вы приводите тип с помощью параметра,
as!
вы принудительно понижаете значение этой переменной, как если бы вы были уверены, что она принадлежит к этому типу, поэтому она безопасна для работы и не приводит к сбою приложения. Это нормально, если переменная действительно того типа, к которому вы ее приводите, иначе у вас будет беспорядок.Тем не менее приведение с помощью
as!
позволит вашему коду компилироваться. Кастинг сas?
- это другая история. На самом деле,as?
объявляет васInt
как совершенно другой тип данных все вместе.Теперь это
Optional(0)
И если вы когда-нибудь пытались сделать домашнее задание, написав
Ваш учитель математики, вероятно, дал бы вам "F". То же самое со Свифтом. За исключением того, что Свифт предпочел бы вообще не компилировать, а не давать оценку. Потому что в конце дня необязательный может фактически быть ноль .
Безопасность первых детей.
источник
'?' означает необязательное цепочечное выражение, которое означает
«!».
источник