可选意外发现nil和崩溃日志信息

Mic*_*use 0 ios swift

我昨天发生了这个问题.我正在处理一段生产代码,这些代码在崩溃信息的某个时刻崩溃了

0   Goga  0x00000001000b90b8 function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Owned To Guaranteed> of Goga.NewViewController.emailButtonPressed (Goga.NewViewController)(ObjectiveC.UIButton) -> () (NewViewController.swift:0)
1   Goga  0x00000001000c0488 Goga.NewViewController.(emailButtonPressed (Goga.NewViewController) -> (ObjectiveC.UIButton) -> ()).(closure #2) (NewViewController.swift:872)
2   Goga  0x00000001000bd250 partial apply forwarder for reabstraction thunk helper from @callee_owned (@in ObjectiveC.UIAlertAction!) -> (@out ()) to @callee_owned (@owned ObjectiveC.UIAlertAction!) -> (@unowned ()) (NewViewController.swift:0)
Run Code Online (Sandbox Code Playgroud)

但是,当我发现错误时,在尝试复制问题数小时后,在崩溃日志中找不到任何错误消息.该错误在XCode中显示为:

在展开Optional值时意外地发现了nil

我的问题是,如何捕获生产代码中的nil-optional错误?

编辑:

只是为原始问题添加一点透视,我在此示例代码中发现了问题:

let cell = tableView.cellForRowAtIndexPath(indexPath)  
cell.textLabel.text = "Hello" // CRASH if the cell is not visible in the view
Run Code Online (Sandbox Code Playgroud)

我应该这样做:

if let cell = tableView.cellForRowAtIndexPath(indexPath) {
  cell.textLabel.text = "Hello" // Never get executed if cell is nil
} 
Run Code Online (Sandbox Code Playgroud)

nhg*_*rif 5

"捕获""nil-optional error"的方法就是正确编写代码.不要滥用强制展开和强制拆卸铸造.

在这种特定情况下,只需阅读崩溃详细信息即可为我们提供一些信息:

1   Goga  0x00000001000c0488 Goga.NewViewController.(emailButtonPressed (Goga.NewViewController) -> (ObjectiveC.UIButton) -> ()).(closure #2) (NewViewController.swift:872)
Run Code Online (Sandbox Code Playgroud)

在872行左右的某个地方NewViewController.swift,你需要展开一些实际的东西nil(因此无法打开).

解决方案是转到第872行NewViewController.swift,查找感叹号的任何出现,确定它是否为强制解包运算符,或者它是否为布尔运算符...如果它是一个强制解包运算符,则使用Swift的可选绑定设计进行修复图案.

可能你正在做这样的事情:

let foo = bar!
Run Code Online (Sandbox Code Playgroud)

或者也许某处bar声明如下:

var bar: AnyObject!
Run Code Online (Sandbox Code Playgroud)

然后它永远不会被初始化(或者在某个时刻被设置为nil),然后因为它被隐式解开,你正在做这样的事情:

let foo: AnyObject = bar
Run Code Online (Sandbox Code Playgroud)

这些都可能导致您正在查看的错误.

是的,在编写代码时隐式展开的选项和强制展开可以使事情稍微方便一些,但最终,所有这意味着你遇到了这些问题,你最终必须追查这些问题.当Swift有足够的工具来确保我们安全时,没有必要这样做nil.