Как использовать (?) И (!) В Swift

72
8

Я новичок в быстром, и у меня возникли трудности с пониманием того, как использовать (!) и (?)


Насколько я знаю, мы можем использовать (?), когда есть экземпляры, в которых переменная может быть равна нулю.
И используйте (!), Когда вы на 100% уверены, что элемент не равен нулю.


1. Рабочие мелкие - необязательные


var john:String?
john = "Is my name"
println(john!)

2. Аварии в Runtime -! не должно быть nil - означает, что это правильно


var john:String?
println(john!)

3. Хорошо работает


var dict: [String:AnyObject] = Dictionary()
dict["name"] = "John"
var str: String = dict["name"]! as String <--- Taking away the (!) says it not convertible to String

4. Не могу запустить/создать - для меня это похоже на 1.


var dict: [String:AnyObject]? = Dictionary() ---error says does not have a member named 'subscript'
dict["name"] = "John"
var str: String = dict["name"]! as String

5. Неожиданно найдено nil при развертывании необязательного значения


var dict: [String:AnyObject] = Dictionary()
dict["name"]? = "John"
var str: String = dict["name"]! as String

Было бы здорово, если бы кто-то помог мне понять эти вещи. Спасибо!

спросил(а) 2014-09-03T11:14:00+04:00 5 лет, 3 месяца назад
1
Решение
81

это немного неверная интерпретация, когда ! 'отмечает' ivar, тогда 100% не может быть nil. может быть. вы можете сказать только, что вы получили значение, которое уже развернуто, поэтому вам не нужно принудительно разворачивать его снова, но это может быть nil.


попробуйте этот пример, например:


var text: String! = "hello"
text = nil;
println(text)

он печатает a nil для вас.


причина, по которой может произойти сбой вашего приложения, - это принудительное развертывание необязательного параметра nil, , который является недопустимым операндом.


# 4

строка за строкой:


var dict: [String:AnyObject]? = Dictionary() // from OP

ваш dict является необязательным, давайте посмотрим, что вы здесь делаете:


dict["name"] = "John" // from OP
var str: String = dict["name"]! as String // from OP

у вас есть необязательный dict, и вы хотели бы как-то использовать его, у вас есть два возможных способа сделать это:


    (A) через дополнительную цепочку;
    (B) с помощью принудительной разворачивания;

(А)


dict?["name"] = "John" // optional chaining

это довольно просто, он назначает новое значение для ключа name, если словарь не является nil, в противном случае цепочка щедро падает, и во время выполнения ничего не происходит.


в перспективе этой строки:


var str: String = dict!["name"]! as String // forcibly unwrapped

он вылетает во время выполнения, если словарь или значение для ключа были nil (согласно первому абзацу говорится: недопустимый операнд для принудительной разворачивания a nil), но str будет John если словарь и ключ оба действительны.


(B)

dict!["name"] = "John" // forcibly unwrapped

он работает как шарм и назначает новое значение для ключа name, если существует dict; но если dict был nil, это точка завершения во время выполнения (aka crash), потому что nil не может быть развернута принудительно (см. выше).


# 5

строка за строкой:


var dict: [String:AnyObject] = Dictionary() // from OP

ваш dict не является необязательным и даже не nil, но словарь буквально пуст, поэтому в нем нет ключа, включая name.


dict["name"]? = "John" // from OP
var str: String = dict["name"]! as String // from OP

необязательная цепочка всегда падает, когда падает какой-либо элемент цепочки, поэтому в коде не будет назначено новое значение, но падение происходит изящно, поэтому вы обходите первую строку о назначении нового значения, но приложение сбои во второй строке, потому что значение не существует, и вы пытаетесь принудительно развернуть его (см. выше о некорректном операнде).


поэтому вам нужно отбросить необязательную цепочку из первой строки, если вы хотите назначить новое значение для несуществующего ключа:


dict["name"] = "John"

необязательная цепочка полезна, если вы не хотите менять исходный словарь с добавлением нового ключа/значения, но вы хотели бы переопределить только существующий:


dict["name"] = "John"
dict["name"]? = "Jack"

в этом случае новое значение будет Jack, поскольку необязательная цепочка не будет падать, поскольку ключ name уже существует с другим значением, поэтому он может быть и будет переопределен; но:


dict["name"] = nil
dict["name"]? = "Jack"

необязательная цепочка будет выпадать и новое значение не будет присвоено для ключа.


ПРИМЕЧАНИЕ. Было бы много других вещей и идей, которые можно было бы рассказать о концепции. исходная документация доступна на сайте Apple в разделе Swift Resources.

ответил(а) 2014-09-03T12:12:00+04:00 5 лет, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема