Что такое необязательное значение в Swift?
Ты можешь использовать
if
а такжеlet
вместе работать со значениями, которые могут отсутствовать. Эти значения представлены как дополнительные. Необязательное значение либо содержит значение, либо содержитnil
чтобы указать, что значение отсутствует. Написать вопросительный знак (?
) после типа значения, чтобы пометить значение как необязательное.
Почему вы хотите использовать необязательное значение?
15 ответов
Необязательным в Swift является тип, который может содержать либо значение, либо отсутствие значения. Факультативные написаны добавлением ?
к любому типу:
var name: String? = "Bertie"
Необязательные (вместе с Generics) являются одной из самых сложных концепций Swift для понимания. Из-за того, как они написаны и используются, легко понять, что они из себя представляют. Сравните необязательное выше с созданием обычной строки:
var name: String = "Bertie" // No "?" after String
Из синтаксиса это выглядит как необязательная строка очень похожа на обычную строку. Это не. Необязательная строка не является строкой с включенной "необязательной" настройкой. Это не особая разновидность String. Строка и необязательная строка - это совершенно разные типы.
Вот самая важная вещь, которую нужно знать: необязательный - это своего рода контейнер. Необязательная строка - это контейнер, который может содержать строку. Необязательный Int - это контейнер, который может содержать Int. Думайте о дополнительной как своего рода посылка. Прежде чем открыть его (или "развернуть" на языке опций), вы не узнаете, содержит ли он что-то или ничего.
Вы можете увидеть, как дополнительные функции реализованы в стандартной библиотеке Swift, введя "Optional" в любой файл Swift и нажав ⌘ по нему. Вот важная часть определения:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
Необязательно это просто enum
который может быть одним из двух случаев: .none
или же .some
, Если это .some
есть связанное значение, которое в приведенном выше примере будет String
"Привет". Необязательный параметр использует Generics для задания типа связанного значения. Тип необязательной строки не String
, его Optional
или точнее Optional<String>
,
Все, что Swift делает с опциями, волшебно, чтобы сделать чтение и написание кода более свободным. К сожалению, это затеняет то, как это на самом деле работает. Я пойду через некоторые трюки позже.
Примечание: я буду много говорить о необязательных переменных, но также неплохо создавать дополнительные константы. Я помечаю все переменные их типом, чтобы облегчить понимание создаваемых типов типов, но вам не нужно это делать в своем собственном коде.
Как создать опцию
Чтобы создать необязательный, добавьте ?
после типа, который вы хотите обернуть. Любой тип может быть необязательным, даже ваши собственные типы. Вы не можете иметь пробел между типом и ?
,
var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)
// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}
Использование опций
Вы можете сравнить дополнительный nil
чтобы увидеть, имеет ли оно значение:
var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
print("There is a name")
}
if name == nil { // Could also use an "else"
print("Name has no value")
}
Это немного сбивает с толку. Это подразумевает, что необязательный - это либо одно, либо другое. Это либо ноль, либо "Боб". Это не так, необязательное не превращается во что-то еще. Сравнение его с nil - это трюк, чтобы сделать код более простым для чтения. Если необязательный параметр равен нулю, это просто означает, что перечисление в настоящее время установлено на .none
,
Только опционально может быть ноль
Если вы попытаетесь установить для необязательной переменной значение nil, вы получите ошибку.
var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'
Еще один способ взглянуть на дополнительные параметры - это дополнение к обычным переменным Swift. Они являются аналогом переменной, которая гарантированно имеет значение. Свифт - это осторожный язык, который ненавидит двусмысленность. Большинство переменных определены как необязательные, но иногда это невозможно. Например, представьте контроллер представления, который загружает изображение либо из кэша, либо из сети. Это может иметь или не иметь это изображение во время создания контроллера представления. Нет способа гарантировать значение для переменной изображения. В этом случае вам придется сделать это необязательно. Начинается как nil
и когда изображение извлекается, необязательный получает значение.
Использование опционально раскрывает намерение программистов. По сравнению с Objective-C, где любой объект может быть нулевым, Swift требует от вас четкого представления о том, когда значение может отсутствовать и когда оно гарантированно существует.
Чтобы использовать необязательный, вы "разверните" его
Необязательный String
не может быть использован вместо фактического String
, Чтобы использовать упакованное значение внутри необязательного, вы должны развернуть его. Самый простой способ развернуть необязательный - это добавить !
после необязательного имени. Это называется "распаковка силы". Возвращает значение внутри необязательного (как исходный тип), но если необязательный nil
, это вызывает сбой во время выполнения. Перед развертыванием вы должны быть уверены, что есть значение.
var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")
name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.
Проверка и использование дополнительного
Поскольку вы всегда должны проверять nil перед развертыванием и использованием необязательного, это распространенный шаблон:
var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
let unwrappedMealPreference: String = mealPreference!
print("Meal: \(unwrappedMealPreference)") // or do something useful
}
В этом шаблоне вы проверяете наличие значения, а затем, когда вы уверены, что оно есть, вы заставляете развернуть его во временную константу для использования. Так как это обычное дело, Swift предлагает ярлык с использованием "если позволено". Это называется "необязательное связывание".
var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
print("Meal: \(unwrappedMealPreference)")
}
Это создает временную константу (или переменную, если вы замените let
с var
) область которого находится только в скобках if. Поскольку использование имени, такого как "unwrappedMealPreference" или "realMealPreference", является бременем, Swift позволяет вам повторно использовать исходное имя переменной, создавая временное имя в области видимости скобок
var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
print("Meal: \(mealPreference)") // separate from the other mealPreference
}
Вот код, демонстрирующий использование другой переменной:
var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"
Необязательное связывание работает, проверяя, равно ли необязательное значение nil. Если это не так, он разворачивает необязательное значение в предоставленную константу и выполняет блок. В Xcode 8.3 и позже (Swift 3.1), попытка напечатать необязательный как это вызовет бесполезное предупреждение. Используйте опционально debugDescription
заставить замолчать
print("\(mealPreference.debugDescription)")
Для чего нужны опции?
Опциональные варианты имеют два варианта использования:
- Вещи, которые могут потерпеть неудачу (я чего-то ожидал, но ничего не получил)
- Вещи, которые сейчас ничто, но могут быть чем-то более поздним (и наоборот)
Некоторые конкретные примеры:
- Свойство, которое может быть там или не там, как
middleName
или жеspouse
вPerson
учебный класс - Метод, который может вернуть значение или ничего, например, поиск соответствия в массиве
- Метод, который может вернуть либо результат, либо получить ошибку и ничего не вернуть, например, попытаться прочитать содержимое файла (которое обычно возвращает данные файла), но файл не существует
- Свойства делегата, которые не всегда должны быть установлены и обычно устанавливаются после инициализации
- За
weak
свойства в классах. То, на что они указывают, может быть установленоnil
в любое время - Большой ресурс, который может быть освобожден для восстановления памяти
- Когда вам нужен способ узнать, когда установлено значение (данные еще не загружены> данные) вместо использования отдельного dataLoaded
Boolean
Необязательные в Objective-C не существуют, но существует эквивалентная концепция, возвращающая ноль. Методы, которые могут вернуть объект, могут вернуть nil. Это означает "отсутствие действительного объекта" и часто используется, чтобы сказать, что что-то пошло не так. Он работает только с объектами Objective-C, но не с примитивами или базовыми типами C (перечисления, структуры). Objective-C часто имел специализированные типы для представления отсутствия этих значений (NSNotFound
что на самом деле NSIntegerMax
, kCLLocationCoordinate2DInvalid
представлять неверную координату, -1
или некоторые отрицательные значения также используются). Кодировщик должен знать об этих специальных значениях, поэтому они должны быть задокументированы и изучены для каждого случая. Если метод не может принять nil
в качестве параметра это должно быть задокументировано. В Objective-C, nil
был указатель так же, как все объекты были определены как указатели, но nil
указал на конкретный (нулевой) адрес. В Свифте nil
это литерал, который означает отсутствие определенного типа.
По сравнению с nil
Раньше вы могли использовать любой дополнительный в качестве Boolean
:
let leatherTrim: CarExtras? = nil
if leatherTrim {
price = price + 1000
}
В более поздних версиях Swift вы должны использовать leatherTrim != nil
, Почему это? Проблема в том, что Boolean
могут быть обернуты в необязательном порядке. Если у вас есть Boolean
как это:
var ambiguous: Boolean? = false
у него есть два типа "ложь", один, где нет значения, и другой, где он имеет значение, но значение false
, Свифт ненавидит двусмысленность, поэтому теперь вы всегда должны проверять nil
,
Вы можете спросить, в чем смысл необязательного Boolean
является? Как и с другими опциями .none
состояние может указывать, что значение пока неизвестно. На другом конце сетевого вызова может быть что-то, что требует некоторого времени для опроса. Необязательные логические значения также называются " трехзначными логическими значениями "
Быстрые трюки
Swift использует некоторые приемы, чтобы позволить опциональным функциям работать. Рассмотрим эти три строки обычного вида дополнительного кода;
var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }
Ни одна из этих строк не должна компилироваться.
- Первая строка устанавливает необязательную строку String с использованием литерала String двух разных типов. Даже если это было
String
типы разные - Вторая строка устанавливает необязательную строку в ноль, два разных типа
- Третья строка сравнивает необязательную строку с нулем, два разных типа
Я рассмотрю некоторые детали реализации опций, которые позволяют этим линиям работать.
Создание необязательного
С помощью ?
для создания необязательного синтаксического сахара, включенного компилятором Swift. Если вы хотите сделать это долгий путь, вы можете создать необязательный, как это:
var name: Optional<String> = Optional("Bob")
Это звонки Optional
первый инициализатор, public init(_ some: Wrapped)
, который выводит связанный тип необязательного из типа, используемого в скобках.
Еще более длинный способ создания и настройки необязательного:
var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")
Установка необязательного nil
Вы можете создать необязательное без начального значения или создать с начальным значением nil
(оба имеют одинаковый результат).
var name: String?
var name: String? = nil
Разрешение опционально равных nil
включен по протоколу ExpressibleByNilLiteral
(ранее названный NilLiteralConvertible
). Необязательный создается с Optional
второй инициализатор, public init(nilLiteral: ())
, Документы говорят, что вы не должны использовать ExpressibleByNilLiteral
для всего, кроме опциональных, так как это изменило бы значение nil в вашем коде, но это возможно сделать:
class Clint: ExpressibleByNilLiteral {
var name: String?
required init(nilLiteral: ()) {
name = "The Man with No Name"
}
}
let clint: Clint = nil // Would normally give an error
print("\(clint.name)")
Тот же протокол позволяет установить уже созданный необязательный параметр для nil
, Хотя это не рекомендуется, вы можете напрямую использовать инициализатор литералов nil:
var name: Optional<String> = Optional(nilLiteral: ())
Сравнивая необязательный к nil
Необязательные определяют два специальных оператора "==" и "!=", Которые вы можете увидеть в Optional
определение. Первый ==
позволяет проверить, равен ли любой необязательный параметр нулю. Два разных дополнительных параметра, для которых установлено значение.none, всегда будут равны, если связанные типы одинаковы. Когда вы сравниваете с nil, за кулисами Swift создает необязательный тип того же связанного типа, для которого установлено значение.none, а затем использует его для сравнения.
// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
print("tuxedoRequired is nil")
}
Второй ==
Оператор позволяет сравнить два варианта. Оба должны быть одного типа, и этот тип должен соответствовать Equatable
(протокол, который позволяет сравнивать вещи с обычным оператором "=="). Свифт (предположительно) разворачивает эти два значения и сравнивает их напрямую. Он также обрабатывает случай, когда один или оба из .none
, Обратите внимание на различие между сравнением с nil
буквальный.
Кроме того, он позволяет сравнивать любые Equatable
введите необязательную упаковку этого типа:
let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
print("It's a match!") // Prints "It's a match!"
}
За кулисами Swift оборачивает необязательное как необязательное перед сравнением. С литералами тоже работает (if 23 == numberFromString {
)
Я сказал, что есть два ==
операторы, но на самом деле есть третий, который позволяет поставить nil
в левой части сравнения
if nil == name { ... }
Нейминг Опционально
Не существует соглашения Swift для именования необязательных типов в отличие от необязательных типов. Люди избегают добавлять что-либо к имени, чтобы показать, что это необязательный параметр (например, "AdditionalMiddleName" или "возможный номер_строки"), и позволяют объявлению показать, что это необязательный тип. Это становится трудным, когда вы хотите назвать что-то для хранения значения из необязательного. Название "middleName" подразумевает, что это тип String, поэтому, когда вы извлекаете из него значение String, вы часто можете получить такие имена, как "actualMiddleName" или "unwrappedMiddleName" или "realMiddleName". Используйте необязательное связывание и повторно используйте имя переменной, чтобы обойти это.
Официальное определение
Из "Основы" на языке программирования Swift:
Swift также вводит необязательные типы, которые обрабатывают отсутствие значения. Необязательные говорят, что "есть значение, и оно равно x" или "нет значения вообще". Необязательные функции аналогичны использованию nil с указателями в Objective-C, но они работают для любого типа, а не только для классов. Дополнительные функции более безопасны и более выразительны, чем нулевые указатели в Objective-C, и являются основой самых мощных функций Swift.
Необязательные примеры являются примером того, что Swift является безопасным типом языка. Swift помогает вам понять типы значений, с которыми может работать ваш код. Если часть вашего кода ожидает строку, тип безопасности не позволяет вам передать ему Int по ошибке. Это позволяет вам выявлять и исправлять ошибки как можно раньше в процессе разработки.
Чтобы закончить, вот стихотворение 1899 года об опциях:
Вчера на лестнице
Я встретил человека, которого там не было
Он не был там снова сегодня
Я бы хотел, чтобы он ушел
Antigonish
Больше ресурсов:
Давайте возьмем пример NSError
, если нет возвращаемой ошибки, вы можете сделать необязательным возвращение Nil. Нет смысла присваивать ему значение, если нет ошибки..
var error: NSError? = nil
Это также позволяет вам иметь значение по умолчанию. Таким образом, вы можете установить для метода значение по умолчанию, если функции ничего не передано
func doesntEnterNumber(x: Int? = 5) -> Bool {
if (x == 5){
return true
} else {
return false
}
}
Я сделал короткий ответ, который подводит итог большей части вышесказанного, чтобы очистить неопределенность, которая была в моей голове как новичка:
В отличие от Objective-C, ни одна переменная не может содержать nil в Swift, поэтому был добавлен необязательный тип переменной (переменные с суффиксом "?"):
var aString = nil //error
Большая разница в том, что дополнительные переменные не хранят значения напрямую (как обычные переменные Obj-C), они содержат два состояния: "имеет значение" или "имеет ноль":
var aString: String? = "Hello, World!"
aString = nil //correct, now it contains the state "has nil"
Таким образом, вы можете проверить эти переменные в разных ситуациях:
if let myString = aString? {
println(myString)
}
else {
println("It's nil") // this will print in our case
}
Используя "!" суффикс, вы также можете получить доступ к значениям, заключенным в них, только если они существуют. (т.е. это не ноль):
let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!
println(anotherString) //it will print "Hello, World!"
Вот почему вам нужно использовать "?" а также "!" и не использовать их все по умолчанию. (это было мое самое большое недоумение)
Я также согласен с ответом выше: необязательный тип не может использоваться как логическое значение.
Вы не можете иметь переменную, которая указывает на nil
в Swift - нет указателей и нулевых указателей. Но в API вы часто хотите иметь возможность указывать либо определенный тип значения, либо отсутствие значения - например, есть ли в моем окне делегат, и если да, то кто это? Опционально это безопасный для памяти и памяти способ Swift.
В целевых C переменные без значения были равны 'nil'(также можно было использовать значения 'nil', такие же, как 0 и false), следовательно, можно было использовать переменные в условных выражениях (переменные со значениями такие же, как 'TRUE) 'и те, у которых нет значений, были равны' ЛОЖЬ ').
Swift обеспечивает безопасность типов, предоставляя "дополнительное значение". т.е. предотвращает возникновение ошибок при назначении переменных разных типов.
Таким образом, в Swift только условные выражения могут содержать только логические значения.
var hw = "Hello World"
Здесь, хотя 'hw' является строкой, ее нельзя использовать в операторе if, как в цели C.
//This is an error
if hw
{..}
Для этого это должно быть создано как,
var nhw : String? = "Hello World"
//This is correct
if nhw
{..}
Необязательное значение позволяет показать отсутствие значения. Немного похоже на NULL в SQL или NSNull в Objective-C. Я думаю, это будет улучшение, поскольку вы можете использовать это даже для "примитивных" типов.
// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)”
Выдержка из: Apple Inc. "Язык программирования Swift". IBooks. https://itun.es/gb/jEUH0.l
Необязательный означает, что Swift не совсем уверен, соответствует ли значение типу: например, Int? означает, что Swift не совсем уверен, является ли число Int.
Чтобы удалить его, есть три метода, которые вы можете использовать.
1) Если вы абсолютно уверены в типе, вы можете использовать восклицательный знак, чтобы принудительно развернуть его, например:
// Here is an optional variable:
var age: Int?
// Here is how you would force unwrap it:
var unwrappedAge = age!
Если вы принудительно распакуете необязательное значение, равное нулю, вы можете столкнуться с этой ошибкой сбоя:
Это не обязательно безопасно, поэтому вот метод, который может предотвратить сбой, если вы не уверены в типе и значении:
Методы 2 и 3 защищают от этой проблемы.
2) Неявно развернутый необязательный
if let unwrappedAge = age {
// continue in here
}
Обратите внимание, что развернутый тип теперь Int, а не Int?,
3) Охранное заявление
guard let unwrappedAge = age else {
// continue in here
}
Отсюда вы можете пойти дальше и использовать переменную unwrapped. Удостоверьтесь, что принудительно разверните (с!), Если вы уверены в типе переменной.
Удачи с вашим проектом!
Когда я начал учиться Swift
было очень трудно понять, почему необязательно.
Давайте думать так. Давай рассмотрим класс Person
который имеет два свойства name
а также company
,
class Person: NSObject {
var name : String //Person must have a value so its no marked as optional
var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible
init(name:String,company:String?) {
self.name = name
self.companyName = company
}
}
Теперь давайте создадим несколько объектов Person
var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil
Но мы не можем пройти Nil
в name
var personWithNoName:Person = Person.init(name: nil, company: nil)
Теперь поговорим о том, почему мы используем optional?
, Давайте рассмотрим ситуацию, когда мы хотим добавить Inc
после названия компании, как apple
будет apple Inc
, Нам нужно добавить Inc
после названия компании и печати.
print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.
Теперь давайте изучим, почему необязательный имеет место.
if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
print(companyString+" Inc") //Will never executed and no crash!!!
}
Позволяет заменить bob
с tom
if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
print(companyString+" Inc") //Will never executed and no crash!!!
}
И поздравляю! мы имеем дело с optional?
Таким образом, точки реализации
- Мы пометим переменную как необязательную, если это возможно
nil
- Если мы хотим использовать эту переменную где-нибудь в коде, компилятор напомнит вам, что нам нужно проверить, правильно ли мы справились с этой переменной, если она содержит
nil
,
Спасибо... Счастливого кодирования
Давайте поэкспериментируем с нижеприведенным кодом Playground. Надеюсь, у вас появится представление о том, что является необязательным, и причина его использования
var sampleString: String? ///Optional, Possible to be nil
sampleString = nil ////perfactly valid as its optional
sampleString = "some value" //Will hold the value
if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.
print(value+value) ////Sample String merged into Two
}
sampleString = nil // value is nil and the
if let value = sampleString{
print(value + value) ///Will Not execute and safe for nil checking
}
// print(sampleString! + sampleString!) //this line Will crash as + operator can not add nil
Что ж...
? (Необязательно) указывает, что ваша переменная может содержать нулевое значение, в то время как ! (unwrapper) указывает, что ваша переменная должна иметь память (или значение), когда она используется (пытается получить значение из нее) во время выполнения.
Основное отличие состоит в том, что необязательное связывание завершается неудачно, когда необязательное значение равно nil, а принудительное развертывание вызывает ошибку времени выполнения, когда необязательное значение равно nil.
Чтобы отразить тот факт, что необязательное сцепление может быть вызвано для значения nil, результатом необязательного вызова цепочки всегда является необязательное значение, даже если запрашиваемое свойство, метод или индекс, возвращают неопциональное значение. Это необязательное возвращаемое значение можно использовать, чтобы проверить, был ли необязательный вызов цепочки успешным (возвращаемое необязательное содержит значение) или не удалось из-за значения nil в цепочке (возвращаемое необязательное значение равно nil).
В частности, результат необязательного вызова цепочки того же типа, что и ожидаемое возвращаемое значение, но заключен в необязательный. Свойство, которое обычно возвращает Int, будет возвращать Int? при доступе через необязательную цепочку.
var defaultNil : Int? // declared variable with default nil value
println(defaultNil) >> nil
var canBeNil : Int? = 4
println(canBeNil) >> optional(4)
canBeNil = nil
println(canBeNil) >> nil
println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper
var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4
var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error
Вот базовое учебное пособие от Apple Developer Committee: Необязательная цепочка
Необязательное сцепление - это процесс запроса и вызова свойств, методов и подписок для необязательного элемента, который в настоящее время может быть равен нулю. Если необязательный параметр содержит значение, вызов свойства, метода или индекса не выполняется; если необязательным является nil, вызов свойства, метода или нижнего индекса возвращает nil. Несколько запросов могут быть объединены в цепочку, и вся цепочка завершится неудачно, если какое-либо звено в цепочке равно нулю.
Чтобы понять глубже, прочитайте ссылку выше.
Необязательным в Swift является тип, который может содержать либо значение, либо отсутствие значения. Факультативные написаны добавлением ? к любому типу:
var name: String?
Вы можете обратиться к этой ссылке, чтобы получить глубокие знания: https://medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870
Это очень просто. Необязательный (в Swift) означает, что переменная/константа может быть нулевой. Вы можете видеть, что язык Kotlin реализует то же самое, но никогда не называет его «необязательным». Например:
var lol: Laugh? = nil
эквивалентно этому в Котлине:
var lol: Laugh? = null
или это в Java:
@Nullable Laugh lol = null;
В самом первом примере, если вы не используете?
символ перед типом объекта, то у вас будет ошибка. Потому что вопросительный знак означает, что переменная/константа может быть нулевой, поэтому называется необязательной.
Есть много ошибок, которые вызваны тем, что люди пытаются использовать значение, которое не установлено, иногда это может привести к сбою, в задаче c попытка вызвать методы нулевой ссылки на объект будет просто проигнорирована, поэтому какая-то часть вашего код не выполняется, и компилятор или написанный код не могут сказать вам, почему. Необязательный аргумент позволяет вам иметь переменные, которые никогда не могут быть нулевыми, и если вы попытаетесь создать их, компилятор может сообщить вам об этом еще до того, как ваш код запустится, или вы можете решить, что объект подходит для того, чтобы быть неопределенным. , и тогда компилятор может сказать вам, когда вы попытаетесь написать что-то, что не учитывает это.
В случае вызова возможного нулевого объекта вы можете просто перейти
object?.doSomthing()
Вы сделали это явным для компилятора и любого тела, которое читает ваш код, что его возможный объект равен нулю, и ничего не произойдет. Иногда у вас есть несколько строк кода, которые вы хотите получить только в том случае, если значение существует, поэтому вы можете сделать
if let obj = object {
obj.doSomthing()
doSomethingto(obj)
}
Два оператора будут выполняться только в том случае, если объект является чем-то, точно так же вы можете остановить остальную часть всего блока кода, если это не что-то
guard let obj = object {
return
}
obj.doSomthing()
doSomethingto(obj)
Это может быть проще читать, если все последующее применимо только в том случае, если объект является чем-то, другая возможность - вы хотите использовать значение по умолчанию.
let obj = object ?? <default-object>
obj.doSomthing()
doSomethingto(obj)
Теперь obj будет присвоен чему-то, даже если это значение по умолчанию для типа
параметры полезны в ситуации, когда значение может не получить значение до тех пор, пока не произойдет какое-то событие, или вы можете использовать установку параметра на ноль, чтобы сказать, что он больше не актуален или его нужно установить снова, и все, что его использует, не имеет смысла он что-то делает с ним, пока он не будет установлен, один из способов, которым я люблю использовать опции, - это сказать мне, что что-то должно быть сделано или что уже было сделано, например
func eventFired() {
guard timer == nil else { return }
timer = scheduleTimerToCall(method, in: 60)
}
func method() {
doSomthing()
timer = nil
}
Этот код sudo может вызывать eventFired много раз, но только при первом вызове запланирован таймер, после выполнения расписания он запускает некоторый метод и устанавливает таймер обратно на ноль, чтобы можно было запланировать другой таймер.
Как только вы поймете, что переменные находятся в неопределенном состоянии, вы можете использовать это для всего.
Вот эквивалентное необязательное объявление в Swift:
var middleName: String?
Это объявление создает переменную с именем middleName типа String. Знак вопроса (?) После типа переменной String указывает, что переменная middleName может содержать значение, которое может быть либо String, либо nil. Любой, кто смотрит на этот код, сразу знает, что middleName может быть нулевым. Это самодокументирование!
Если вы не укажете начальное значение для необязательной константы или переменной (как показано выше), для вас автоматически будет установлено значение nil. Если вы предпочитаете, вы можете явно установить начальное значение равным nil:
var middleName: String? = nil
для более подробной информации для дополнительной читайте ссылку ниже
http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values