【问题标题】:How to use (?) and (!) in Swift如何在 Swift 中使用 (?) 和 (!)
【发布时间】:2014-10-27 15:58:26
【问题描述】:

我是 swift 新手,在理解如何使用 (!) 和 (?) 方面有些困难

据我所知,当存在变量可以为零的实例时,我们可以使用 (?)。 并在您 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

如果有人能帮助我理解这些事情,那就太好了。谢谢!

【问题讨论】:

  • 考虑到取消引用 nil Object! 会导致异常,我想要的不仅仅是“非常确定”!
  • 我已将非常确定更改为 100% 确定。是的,对于第二个,我知道它会根据(!)的定义而崩溃。但是说 5 哪里有?在字典中,为什么上面有 John 时会说 found nil?
  • @ShlbyPuerto,当!“标记”一个 ivar 时认为 100% 不能是 nil,这有点误导。有可能。你只能说,你得到了已经解包的值,所以你不需要再次强制解包——但它可以是nil,试试这个例子:var text: String! = "hello"; text = nil; println(text),它会为您打印nil。你的应用程序崩溃的原因是你强制解开一个可选的nil,这是无效的操作数。
  • @holex 是的,我明白这一点。谢谢。但我认为这篇文章对于我想要问的内容有点复杂。但这不是没有。 2(表示理解正确)。我在 4 和 5 上更复杂。其中 4 对我来说有点类似于 1,但我确定我错了,这就是我需要帮助的原因。 For 5 为什么当我分配给 John 时它是 nil?
  • @ShlbyPuerto,请参阅我关于 4 或 5 的回答,我个人没有看到它们有任何并发​​症,它们只是不正确。如果您还有其他问题,请告诉我。 :)

标签: ios string dictionary swift


【解决方案1】:

!'标记'一个 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) 通过强制展开;

(A)

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

这很简单,如果字典不是nil,它会为键name分配新值,否则链会大量下降,运行时不会发生任何事情。

从这条线的角度来看:

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

如果字典或键的值是nil(根据第一段所说:强制展开nil 的无效操作数),它会在运行时崩溃,但str 将是John如果字典和键做有效的对象。

(B)

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

它就像一个魅力,如果dict 存在,则为键name 分配新值;但如果dictnil,那是运行时的终止点(又名崩溃),因为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 部分下找到。

【讨论】:

  • 感谢这些,帮助很大。至于文档,我有时不明白什么是什么,什么不是。这就是我发布类似内容的原因。
猜你喜欢
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
相关资源
最近更新 更多