如何在 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)eexpression 的缩写,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 中打印调用堆栈?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中获取调用堆栈列表?

谁创建和拥有调用堆栈以及调用堆栈如何在多线程中工作?

如何打印内核调用堆栈及函数名

如何在调用函数时打印它们?

如何使用先前堆栈中的名称打印变量参数?

如何将堆栈跟踪打印到控制台/登录 Cocoa?