我在 Xcode 8.2.1 中有一个用 Swift 2 编写的 iOS 应用程序,它是为 iOS 10.2 构建的。
我从 TestFlight 收到了许多崩溃报告,尽管有符号化,但除了堆栈跟踪(没有参数值、没有局部变量、没有堆对象等)之外,没有任何崩溃日志显示任何程序状态。
。但是在这些函数中,我可以看到可能会失败的代码(例如强制解包),但崩溃日志没有告诉我它在哪里或为什么失败。
在 Xcode 中调试时,我可以使用fatalError(message: String)
,我可以在其中放置自己的消息,例如"functionFoo returned nil"
或"variable bar == "" + bar + """
,除非使用 TestFlight 或 App Store 部署时,fatalError
将被命中并且程序终止,但message
值不会保存到崩溃日志中,使其毫无意义。
在其他环境中,如 C#/.NET 和 Java,我可以简单地throw new SomeExceptionType("my message")
,所有信息都可以在我拥有的任何全局catch(Exception)
处理程序中找到。
如何在 iOS/Swift 中实现相同的目标?
Swift 确实支持错误处理。您可以通过确认协议或使用现有错误类型来创建自己的错误类型Error
然后通过调用throw error
引发错误。
但是 Swift 会强制你向任何可能抛出错误的代码添加错误处理。有多种方法可以在 swift 中处理错误。
-
将
throws
关键字应用于函数,这表示函数在调用时可能会引发错误,并且错误应由调用方处理。func canThrowErrors() throws -> String
-
使用关键字调用方法时
throws
必须在调用开始时添加try
关键字。所有这些try
调用都应通过将throws
应用于方法来仅传播错误或包装在 do-catch 块中来处理:do { try canThrowErrors() try canThrowOtherErrors() } catch is SpecificError { // handling only specific error type } catch let error as SpecificError { // catches only specific error for type } catch { // catches all errors }
-
此外,您可以使用
try?
和try!
进行抛出函数调用,以禁用错误传播并检索在发生错误和运行时断言时分别返回 nil 的可选结果。
通过强制您在编译时处理所有错误,swift 避免了任何未定义的运行时行为和调试噩梦。
我建议仅在无法在不使应用程序崩溃的情况下从状态恢复的情况下使用fatalError
或任何其他运行时断言。 不幸的是,无法处理来自fatalError
的错误,因为它的使用仅用于此类场景。此外,在崩溃日志中,您只会获得导致崩溃的行号,以获取有关崩溃原因的其他信息,我建议使用自定义日志记录或分析。