我是 swift 的新手,在理解如何使用 (!) 和 (?) 时遇到了一些困难
据我所知,当存在变量可以为 nil 的实例时,我们可以使用 (?)。 并在您 100% 确定该项目不为零时使用 (!)。
<强>1。工作正常 - 可选
var john:String?
john = "Is my name"
println(john!)
<强>2。运行时崩溃 - !不能为 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's 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)
它为你打印一个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
它非常简单,如果字典不是nil
,它会为键 name
分配新值,否则链会大大下降,运行时什么也不会发生。
从这条线的角度来看:
var str: String = dict!["name"]! as String // forcibly unwrapped
如果字典或键的值为 nil
,它会在运行时崩溃(根据第一段所述:无效的操作数强制展开 nil
),但是 str
将是 John
如果字典和键 都 是有效对象。
(乙)
dict!["name"] = "John" // forcibly unwrapped
它就像一个魅力,如果 dict
存在,它会为键 name
分配新值;但是如果 dict
是 nil
,那是运行时的终止点(又名崩溃),因为 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 部分找到.
关于ios - 如何在 Swift 中使用 (?) 和 (!),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25639431/