Как использовать (?) И (!) В Swift
Я новичок в быстром, и у меня возникли трудности с пониманием того, как использовать (!) и (?)
Насколько я знаю, мы можем использовать (?), когда есть экземпляры, в которых переменная может быть равна нулю.
И используйте (!), Когда вы на 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
Было бы здорово, если бы кто-то помог мне понять эти вещи. Спасибо!
это немного неверная интерпретация, когда !
'отмечает' 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.