Що таке необов'язкове значення у Swift?


267

З документації Apple :

Ви можете використовувати ifта letразом працювати з значеннями, які можуть бути відсутніми. Ці значення представлені як необов'язкові. Необов’язкове значення або містить значення, або містить, nilщоб вказати, що значення відсутнє. Напишіть знак питання ( ?) після типу значення, щоб позначити значення як необов'язкове.

Чому ви хочете використовувати необов’язкове значення?



1
Необов'язково також можна розглядати як реалізацію Варіанту / Можливо, монаду . Цей блог тут добре допомагає пояснити, що інакше є важкою концепцією.
StuartLC

tldr: "Свіфт повинен вам зрозуміти, коли значення може бути відсутнім і коли воно гарантовано існує". від відмінної відповіді
Неван Кінга

Відповіді:


531

Необов’язковий варіант Swift - це тип, який може містити або значення, або не має значення. Необов’язкові записуються шляхом додавання ?до будь-якого типу:

var name: String? = "Bertie"

Необов'язкові параметри (поряд із Generics) - одна з найскладніших концепцій Свіфта. Через те, як вони написані та використовуються, легко зрозуміти неправильне уявлення про те, що вони є. Порівняйте додатковий варіант із створенням звичайної рядки:

var name: String = "Bertie" // No "?" after String

З синтаксису схоже, що необов'язковий рядок дуже схожий на звичайний рядок. Це не. Необов’язковий рядок - це не рядок із увімкненою "необов'язковою" настройкою. Це не особлива різноманітність String. Рядок і необов'язковий рядок - це абсолютно різні типи.

Ось найважливіше, що потрібно знати: Необов’язково - це тип контейнера. Додатковий рядок - це контейнер, який може містити рядок. Необов'язковий Int - контейнер, який може містити Int. Подумайте про необов'язковий як вид посилки. Перш ніж відкрити його (або "розмотати" мовою за бажанням), ви не знатимете, чи містить він щось чи нічого.

Ви можете побачити, як додаткові елементи реалізовані в стандартній бібліотеці Swift, ввівши "Необов’язково" у будь-який файл 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")
}

Це трохи заплутано. Це означає, що необов'язково - це або інше, або інше. Це або нуль, або це "Боб". Це неправда, необов'язковий не перетворюється на щось інше. Порівнювати його з нулем - трюк, щоб зробити простіший для читання код. Якщо необов'язково дорівнює нулю, це просто означає, що перерахунок наразі встановлений .none.


Тільки необов'язкові можуть бути нульовими

Якщо ви спробуєте встановити необов'язкову змінну до нуля, ви отримаєте помилку.

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.

Перевірка та використання необов’язкового

Оскільки ви завжди повинні перевіряти наявність нуля перед тим, як розгортати та використовувати необов'язковий, це звичайний зразок:

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), областю дії якого тільки в межах , якщо це брекети - х. Оскільки використання імені типу "unrappedMealPreference" або "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")"

Необов'язкове прив'язування працює, перевіряючи, чи необов'язковий дорівнює нулю. Якщо цього не відбувається, він розгортає необов'язкове в задану константу і виконує блок. У Xcode 8.3 та пізніших версіях (Swift 3.1) спроба надрукувати подібну необов’язковість спричинить марне попередження. Використовуйте необов’язкові, debugDescriptionщоб заглушити це:

print("\(mealPreference.debugDescription)")

Для чого необов’язкові?

Необов’язково два випадки використання:

  1. Те, що може вийти з ладу (я чогось очікував, але нічого не отримав)
  2. Речі, які зараз є нічим, але можуть бути чимось пізніше (і навпаки)

Деякі конкретні приклади:

  • Властивість, яка може бути там чи ні, як у класі , так middleNameі spouseв нійPerson
  • Метод, який може повернути значення або нічого, наприклад пошук відповідності в масиві
  • Метод, який може повернути результат або отримати помилку і нічого не повернути, як, наприклад, спроба прочитати вміст файлу (який зазвичай повертає дані файлу), але файл не існує
  • Властивості делегування, які не завжди потрібно встановлювати і зазвичай встановлюються після ініціалізації
  • Для weakвластивостей у класах. Те, на що вони вказують, може налаштуватись nilу будь-який час
  • Великий ресурс, який, можливо, доведеться випустити для відновлення пам'яті
  • Коли вам потрібен спосіб дізнатися, коли встановлено значення (дані ще не завантажені> дані), а не використовувати окремі завантажені дані Boolean

Необов’язковість не існує в Objective-C, але існує рівнозначна концепція, яка повертає нуль. Методи, які можуть повернути об'єкт, можуть замість цього повернути нуль. Це прийнято означати "відсутність дійсного об'єкта" і часто використовується для того, щоб сказати, що щось пішло не так. Він працює лише з об'єктами Objective-C, а не з примітивами або основними типами С (перерахунки, структури). Objective-C часто спеціалізувався типами являє відсутність цих значень ( NSNotFoundяка насправді NSIntegerMax, kCLLocationCoordinate2DInvalidявляє неприпустимі координати, -1або яке - або негативне значення також використовується). Кодер повинен знати про ці особливі значення, тому вони повинні бути задокументовані та вивчені для кожного випадку. Якщо метод не може взятись nilза параметр, це необхідно задокументувати. В Objective-C,nilбув покажчиком так само, як усі об'єкти визначалися як покажчики, але nilвказував на конкретну (нульову) адресу. У Swift 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 to nil"
  • Третій рядок порівнює необов'язковий рядок з нулем, два різні типи

Я ознайомлюсь із деякими деталями реалізації додаткових опцій, які дозволяють цим рядкам працювати.


Створення необов'язкового

Використовувати ?для створення необов'язкового є синтаксичний цукор, включений компілятором 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другим ініціалізатор «S, public init(nilLiteral: ()). Документи говорять, що не слід використовувати ExpressibleByNilLiteralнічого, крім додаткового, оскільки це змінило б значення нуля у вашому коді, але це можливо:

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 literal безпосередньо:

var name: Optional<String> = Optional(nilLiteral: ())

Порівняння необов’язкового до nil

Додаткові параметри визначають двох спеціальних операторів "==" та "! =", Які ви можете побачити у Optionalвизначенні. Перший ==дозволяє перевірити, чи будь-який необов'язковий дорівнює нулю. Дві різні необов'язкові параметри, встановлені на .none, завжди будуть рівними, якщо асоційовані типи однакові. Коли ви порівнюєте з нулем, за лаштунками 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 для назви необов'язкових типів, відмінних від необов'язкових типів. Люди уникають додати щось до імені, щоб показати, що це необов’язкове (наприклад, "optionalMiddleName" або "possibleNumberAsString"), і нехай декларація показує, що це необов'язковий тип. Це стає складним, коли ви хочете назвати щось, щоб утримувати значення від необов'язкового. Ім'я "middleName" означає, що це тип String, тому коли ви виймаєте з нього значення String, ви часто можете закінчуватись такими іменами, як "фактичнийMiddleName" або "unpappedMiddleName" або "realMiddleName". Використовуйте необов'язкове прив'язування та повторно використовуйте ім’я змінної, щоб обійти це.


Офіційне визначення

З розділу "Основи" мови швидкого програмування :

Swift також вводить необов'язкові типи, які обробляють відсутність значення. Необов’язкові кажуть або "є значення, і воно дорівнює х", або "значення взагалі не існує". Необов'язкові подібні до використання нуля з покажчиками в Objective-C, але вони працюють для будь-якого типу, а не лише для класів. Додаткові опції безпечніші та виразніші за нульові покажчики в Objective-C і лежать в основі багатьох найпотужніших функцій Свіфта.

Необов’язкові - приклад того, що Swift - це безпечна мова. Swift допомагає зрозуміти типи значень, з якими може працювати ваш код. Якщо частина вашого коду очікує String, введіть безпеку, яка не дозволяє вам помилково передати його Int. Це дає змогу фіксувати та виправляти помилки якомога раніше в процесі розробки.


На закінчення, ось вірш 1899 р. Про необов’язкові:

Вчора на сходах
я зустрів чоловіка, якого там
не було. Сьогодні його знову не було,
я б хотів, щоб він пішов

Антигоніш


Більше ресурсів:


5
@KaanDedeoglu На жаль, Стів дуже необов’язковий. Він був тут, а зараз його немає.
король Неван

19
if myStringбільше не компілюється Вам потрібно if myString != nil. Дивіться документацію .
Панг

5
найкраще і зрозуміліше пояснення? і! використання в Swift я знайшов в Інтернеті. дякую
mindbomb

2
mateo глибоко пояснює необов’язкові, досягаючи глибини та простих прикладів.
iluvatar_GR

4
Дякую за це пояснення, воно набагато зрозуміліше, ніж власна документація Apple.
yesthisisjoe

16

Візьмемо для прикладу NSError, якщо помилка не повертається, ви хочете зробити її необов'язковою для повернення Nil Немає сенсу присвоювати йому значення, якщо не буде помилки.

var error: NSError? = nil

Це також дозволяє мати значення за замовчуванням. Таким чином, ви можете встановити для методу значення за замовчуванням, якщо функція нічого не передала

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

Речення "Якщо це нуль, результат будь-якого виразу з ним також є нульовим", просто неправильне. func isNil<T>(t: T?) -> Bool { return t == nil }повернеться, trueнавіть якщо в виразі є необов’язкове значення nil.
повернення справжнього

Неймовірно поганий зразок коду. Ви не могли б придумати щось краще? Чому б не просто return x == 5? Що таке особливе у 5?
Атомоск

Ні, 2 роки тому я не міг придумати щось краще. Сьогодні так, але чи це сприймає справу? так. Дякую за вклад @Atomosk, це дуже корисно.
Джон Різельвато

12

Ви не можете мати змінну, яка вказує на nilSwift - немає вказівників та нульових покажчиків. Але в API вам часто хочеться вказати або певний вид значення, або відсутність значення - наприклад, у моєму вікні є делегат, і якщо так, хто це? Необов'язково - безпечний для пам'яті спосіб, який захищає пам'ять.


11

Я зробив коротку відповідь, яка підсумовує більшу частину сказаного, щоб очистити невпевненість, яка була в моїй голові як початківця:

На противагу Objective-C жодна змінна не може містити нуля в 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!"

Ось чому вам потрібно використовувати "?" і "!" і не використовувати їх усі за замовчуванням. (це було моє найбільше здивування)

Я також згоден з відповіддю вище: необов'язковий тип не може використовуватися як булева .


7

У об'єктивних змінних C, що не мають значення, було рівним 'nil' (також можна було використовувати значення 'nil' такі ж, як 0 і false), отже, можна було використовувати змінні в умовних операторах (Змінні зі значеннями такі ж, як 'TRUE ", а значення, які не мають значення, дорівнювали" FALSE ").

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

 {..}

5

Необов’язкове значення дозволяє показувати відсутність значення. Трохи схожий на 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. "Мова швидкого програмування". iBooks. https://itun.es/gb/jEUH0.l


6
nil- це лише синтаксичний цукор для константи перерахунку OptionalValue<T>.None(де Tтип відповідає відповідному контексту, де ви використовуєте nil). ?- це ярлик для OptionalValue<T>.Some(T).
рикстер

4

Необов'язково означає, що Swift не зовсім впевнений, чи відповідає значення типу: наприклад, Int? означає, що Свіфт не зовсім впевнений, чи є це число Int.

Щоб видалити його, можна застосувати три методи.

1) Якщо ви абсолютно впевнені в типі, ви можете використовувати знак оклику, щоб змусити його розгортати, наприклад:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

Якщо ви примусово розгорнули необов’язковий показник і він дорівнює нулю, ви можете зіткнутися з цією помилкою аварії:

введіть тут опис зображення

Це не обов'язково безпечно, тому ось метод, який може запобігти збоїв у випадку, якщо ви не впевнені в типі та значенні:

Методи 2 та три захищають від цієї проблеми.

2) Необов’язково розмотується необов’язково

 if let unwrappedAge = age {

 // continue in here

 }

Зауважте, що розгорнутий тип тепер Int , а не Int? .

3) Заява охоронця

 guard let unwrappedAge = age else { 
   // continue in here
 }

Звідси ви можете йти вперед і використовувати розпаковану змінну. Переконайтеся, що потрібно примусово розкручувати (з!), Якщо ви впевнені в типі змінної.

Успіхів у вашому проекті!


1

Коли я почав вчитися, 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?

Тож бали реалізації є

  1. Ми позначимо змінну як необов'язкову, якщо це можливо nil
  2. Якщо ми хочемо використовувати цю змінну десь у компіляторі коду, це нагадує вам, що нам потрібно перевірити, чи ми маємо належну справу з цією змінною, чи вона містить nil .

Дякую ... Щасливе кодування


0

Дозволяє експериментувати з ігровим майданчиком нижче коду. Я сподіваюся, що зрозуміє, що є необов’язковим, та причину його використання.

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

0

З https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionsChaining.html :

Необов’язковий ланцюжок - це процес запиту та виклику властивостей, методів та підписок на необов'язковій, яка наразі може бути нульовою. Якщо необов'язковий містить значення, властивість, метод або виклик підрядника є успішним; якщо необов'язковим є нуль, властивість, метод або виклик підрядника повертає нуль. Кілька запитів можна зв'язати разом, і вся ланцюг виходить витончено, якщо будь-яка ланка ланцюга є нульовою.

Щоб зрозуміти глибше, прочитайте посилання вище.


0

Ну...

? (Необов’язково) вказує, що ваша змінна може містити значення нуля, хоча ! (unrapper) вказує, що ваша змінна повинна мати пам'ять (або значення), коли вона використовується (намагалася отримати значення з неї) під час виконання.

Основна відмінність полягає в тому, що необов'язкове ланцюжок виходить вишукано, коли необов'язковий нуль, тоді як примусове розгортання викликає помилку виконання, коли необов'язковий нуль.

Щоб відобразити той факт, що необов'язковий ланцюжок може бути викликаний нульовим значенням, результат необов'язкового виклику ланцюга завжди є необов'язковим значенням, навіть якщо властивість, метод чи підписник, який ви запитуєте, повертає необов'язкове значення. Ви можете використовувати це необов'язкове повернене значення, щоб перевірити, чи був необов'язковий виклик ланцюга успішним (повернений необов'язковий вміст містить значення) чи не вдався через нульове значення у ланцюжку (повернене необов'язкове значення - нульове).

Зокрема, результат необов'язкового ланцюгового виклику того ж типу, що і очікуване повернене значення, але загорнутий у необов'язковий. Властивість, яка зазвичай повертає 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: Необов’язковий ланцюжок


0

Необов’язковий варіант Swift - це тип, який може містити або значення, або не має значення. Необов’язкові записуються шляхом додавання ? до будь-якого типу:

var name: String?

Ви можете посилатися на це посилання, щоб отримати глибокі знання: https://medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870


-1

Ось еквівалентна додаткова декларація у Swift:

var middleName: String?

Ця декларація створює змінну з назвою middleName типу String. Знак питання (?) Після типу змінної String вказує на те, що змінна middleName може містити значення, яке може бути або String, або nil. Кожен, хто дивиться на цей код, відразу знає, що середнє ім'я може бути нульовим. Це самодокументування!

Якщо ви не вказуєте початкове значення для необов'язкової константи або змінної (як показано вище), значення автоматично встановлюється для нуля. Якщо ви хочете, ви можете явно встановити початкове значення на нуль:

var middleName: String? = nil

для більш детальної інформації для факультативного читання нижче за посиланням

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values


використовуйте це, var middleName: Рядок! = ""
Гаурав
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.