Использование Swift Implicitly Unwrapped Optional до доступности обнуляемости
В блоге Apple об обнуляемости они упоминают это:
"... в Swift существует сильное различие между необязательными и необязательными ссылками, например, NSView и NSView?, тогда как Objective-C представляет оба этих двух типа как NSView *. Поскольку компилятор Swift не может быть уверен, что конкретный NSView * является необязательным или нет, тип приведен в Swift как неявно развернутый необязательный, NSView! "
Означает ли это ранее, когда объявляют методы Objective C как возвращающие неявно развернутый необязательный параметр в Swift, он может фактически потерпеть крах (поскольку некоторые из методов, объявленных с неявно развернутым необязательным необязательным, могут возвращать ноль)? Или Apple следит за тем, чтобы только те методы Objective C, которые абсолютно не возвращали nil, объявлялись как неявно развернутые необязательные?
2 ответа
Каркасы Apple не являются чем-то особенным. В начале все (каждый объект), который вы использовали из Objective-C в Swift, было неявно развернутым необязательным. Это было потому, что каждый указатель в Objective-C мог возвращать nil
,
На самом деле, даже в эпоху аннотаций обнуляемости Objective-C не исключено, что метод, аннотированный как nonnull
мог вернуться nil
, Objective-C не применяет правила обнуляемости, он просто предоставляет средство для аннотирования вашего кода, чтобы его было безопаснее использовать из Swift. В случае с фреймворками Apple я бы поспорил, что это довольно безопасная ставка, что у вас не будет этой проблемы. Или, если вы это сделаете, следующая версия Xcode это исправит.
Но опять же, нет ничего особенного в неявно развернутых опциях, поступающих из библиотек и сред Objective-C. Единственное, что говорит вам неявно развернутый необязательный параметр, - это то, что автор фреймворка еще не предпринял попытки аннотировать свою библиотеку (вы не можете оставить неявно развернутый необязательный параметр в аннотированной библиотеке).И да, эти неявно развернутые параметры могут бытьnil
и они могут разбить ваше приложение.
В случае Apple, если по какой-то причине вы используете, скажем, Xcode 7 и Xcode 6 в разных проектах, если вы берете что-то, что аннотации обновлений Xcode 7 объявлены как необязательные, то предполагается, что в Xcode неявно развернутая необязательная версия 6 никогда не будет nil
может сработать. Но если вы возьмете что-то, что является необязательным в Xcode 7, предполагая, что неявно развернутая версия из Xcode 6 никогда не будет nil
вероятно, у вас есть приличная вероятность поломки вашего приложения.
В конечном счете, в Swift наше использование неявно развернутых опций должно быть немногочисленным. Основное использование неявно развернутых необязательных опций в основном должно быть зарезервировано для свойств класса, которые не могут быть установлены до возврата инициализации класса (например, @IBOutlets
в виде контроллера). В противном случае, они склонны быть источником многочисленных вопросов "Неожиданно найден ноль" здесь, на переполнении стека.
На вопрос "Зачем возвращать неявно развернутый необязательный, а не необязательный?", Несколько моментов...
Во-первых, это вопрос дизайна языка. Я не в команде разработчиков языка Objective-C или Swift, и вряд ли кто-то из этих команд зайдет и ответит на этот вопрос...
Во-вторых, вот как языки предназначены для взаимодействия. Любой файл Objective-C, к которому не добавлены аннотации обнуляемости, будет обрабатываться так, как если бы в Swift все неявно было развернуто.
В-третьих, причина неявных опций заключается в том, что она значительно сокращает многословность if let
необязательные операторы и т. д., не гарантирующие, что переменная non-nil
, Основная причина этого, вероятно, в том, что вы полагаете, что большинство этих методов на самом деле никогда не возвращаются nil
,
В-четвертых, если вы знаете, у кого есть шанс быть nil
а какие нет, на самом деле вы можете пойти дальше и написать свой код Swift таким образом, который обрабатывает оба предположения о том, каким образом код Objective-C будет аннотирован.
Например, с неявно развернутым необязательным, конечно, вы можете обращаться с ним как с необязательным и удалять некоторые мелкие детали, связанные с развертыванием.
Кроме того, с неявно развернутым необязательным, если вы думаете, что это может быть nil
все дополнительные материалы для распаковки могут работать с ним.
Пример:
override func someFunc(implicitVal: String!) -> String {
return implicitVal ?? "It was nil!"
}
override func someOtherFunc(implicitVal: String!) -> String {
return implicitVal
}
Если бы мы приняли их все как дополнительные, второй пример не сработал бы
Если бы мы предполагали их как необязательные, первый пример не сработал бы.
Неявно развернутые опциональные возможности позволяют разработчику Swift обращаться с ними так же, как если бы они сделали правильное предположение о вероятности того, что значение nil
,
Означает ли это ранее, когда объявляют методы Objective C как возвращающие неявно развернутый необязательный параметр в Swift, он может фактически потерпеть крах (поскольку некоторые из методов, объявленных с неявно развернутым необязательным необязательным, могут возвращать ноль)?
Нет. Неявно развернутый необязательный является необязательным, что означает nil
это вполне приемлемое значение для него. Наличие неявно развернутого необязательного nil
не вылетает, только если вы пытаетесь получить доступ к члену на нем напрямую без опционального связывания или опционального связывания, происходит сбой.
Или Apple следит за тем, чтобы только те методы Objective C, которые абсолютно не возвращали nil, объявлялись как неявно развернутые необязательные?
Если бы это было известно, чтобы не вернуться nil
затем Apple после аудита объявит его необязательным, а не неявно развернутым необязательным. Только если не известно, может ли он вернуться nil
или нет, он возвращает неявно-развернутый необязательно.