如何在 Swift 中打印调用堆栈?
Posted
技术标签:
【中文标题】如何在 Swift 中打印调用堆栈?【英文标题】:How to print call stack in Swift? 【发布时间】:2015-08-25 14:44:27 【问题描述】:在 Objective-C 中,您可以通过执行以下操作来打印调用堆栈:
NSLog(@"%@", [NSThread callStackSymbols]);
在不使用 Foundation 类的情况下如何在 Swift 中做到这一点?
【问题讨论】:
操场上的自动补全给了我:NSLog(NSThread.callStackSymbols())
。
抱歉,我应该澄清一下——不使用 Foundation 类。
通过使用基础类。这不是邪恶的。 Cocoa/Cocoa touch 的大部分功能都是围绕 Foundation 类构建的。需要时使用它们。
@DuncanC 同意,但想知道一种严格的 Swift 代码的方法。
如果不使用 Foundation 类,我就无法做到这一点。如果不使用基础类,我无法编写 ios 或 Mac OS GUI 应用程序。您可以使用纯 Swift 代码调用 Foundation Class 方法,但您仍然需要使用 Foundation Classes。
【参考方案1】:
正如 Jacobson 所说,使用以下内容:
斯威夫特 2:
print(NSThread.callStackSymbols())
斯威夫特 3 / 斯威夫特 4:
print(Thread.callStackSymbols)
这是 Swift 代码。它使用的是 Foundation 方法,但你在 iOS 上所做的 90% 以上也是如此。
编辑:
请注意,如果您使用以下格式,格式看起来会更好:
Thread.callStackSymbols.forEachprint($0)
您可以从调试器命令行键入
e Thread.callStackSymbols.forEachprint($0)
【讨论】:
效果很好,但我在控制台窗口中的布局混乱,看起来像是一些选项卡/空白问题。使用 Xcode 7.2 这似乎可行,有没有办法获得更具可读性的堆栈跟踪,例如当您在 Xcode 中放置断点时,您可以看到函数调用及其参数,就像在 swift 源文件中一样,但是“转储”给出了一个不太可读的版本,带有地址等 @AlexMan,从 Swift 3 开始,是的。但是,这篇文章是在 Swift 3 发布之前发布的。 我得到这个:错误:未知命令速记后缀:'(Thread.callStackSymbols)' 错误:无法识别命令'print(Thread.callStackSymbols)'。 @Kingalione,如果您想在调试器中输入它,您需要输入e print(Thread.callStackSymbols)
或e Thread.callStackSymbols.forEachprint($0)
。 e
是 expression
的缩写,LLDB 命令告诉调试器评估您键入的内容作为 Swift 语句。【参考方案2】:
对于 Swift 3 使用:
print(Thread.callStackSymbols)
或者为了更好的格式
for symbol: String in Thread.callStackSymbols
print(symbol)
【讨论】:
或者更快捷的 3:Thread.callStackSymbols.forEach print($0)
【参考方案3】:
这会稍微提高输出。
for symbol: String in NSThread.callStackSymbols()
NSLog("%@", symbol)
【讨论】:
为什么不在for循环中使用Swift的print
而不是NSLog
来显示每一行? NSLog
相当“嘈杂”(每一行都以时间戳、有关进程和线程的信息等开头)【参考方案4】:
这是我在 github 上找到的一个很棒的实用程序类:
https://github.com/nurun/swiftcallstacktrace
您将获得任何堆栈跟踪符号的元组(类、方法),以便您可以进行干净的打印输出。
CallStackAnalyser.classAndMethodForStackSymbol(NSThread.callStackSymbols()[2])
编辑:swift 4.1 更新
https://github.com/GDXRepo/CallStackParser
【讨论】:
不幸的是,这不适用于 Swift 3,而且看起来没有简单的方法可以用 Swift 3 对函数名称进行“分解”。虽然这个项目可能是一种可能性(还没有尝试过)我自己):github.com/mattgallagher/CwlDemangle 看起来有人努力让它与新版本的 Swift 一起工作:github.com/GDXRepo/CallStackParser【参考方案5】:我需要将调用堆栈写入日志文件,因此我对其进行了调整。
var ErrorStack = String()
Thread.callStackSymbols.forEach
print($0)
ErrorStack = "\(ErrorStack)\n" + $0
【讨论】:
以上是关于如何在 Swift 中打印调用堆栈?的主要内容,如果未能解决你的问题,请参考以下文章