Xcode如何隐藏调用栈中的第三方调用
How to hide the third-party calls in the call stack in Xcode
当我使用 Realm 或 RxSwift 时出现异常,我得到这些我不关心的巨大调用堆栈,并且必须找到我的代码中的一两行。我只想在调用堆栈上显示来自目标 运行 的符号,而不是链接库。我怎样才能隐藏这些?
我不知道有什么方法可以过滤 Xcode 显示的内容,但您可能会发现 lldb 的 python 脚本很有帮助。至少有三种可能的方法来过滤堆栈:
- 框架名称
- 图书馆
- 来源路径
首先,要按名称过滤堆栈,可以使用正则表达式来检查函数名称。正则表达式可以匹配您要删除的帧,也可以匹配您想要保留的帧。从给定的堆栈跟踪中,我无法判断您想要保留哪些,因此我将演示如何删除 Realm 框架:
(lldb) script
import re
for frame in lldb.thread:
if not re.search("[Rr]ealm|RLM", frame.name):
print(f"{frame.idx}: {frame.name}")
按函数名称匹配并不总是理想的,它可能是一个很长或很复杂的正则表达式。如果你要过滤的库恰好是dynamic库或框架,那么最简单的方法就是按“模块”过滤:
(lldb) script
for frame in lldb.thread:
if frame.module.file.basename != "Realm":
print(f"{frame.idx}: {frame.name}")
第三个选项是按与每个帧关联的源路径进行过滤。我不知道这对 Realm 有用(这取决于调试信息),但我已经用 RxSwift 完成了。在此示例中,将不会打印源路径中具有 RxSwift/
的帧:
(lldb) script
for frame in lldb.thread:
if "RxSwift/" not in frame.line_entry.file.fullpath:
print(f"{frame.idx}: {frame.name}")
可重复使用的命令
可以结合使用这些方法来制作适合您的项目的堆栈跟踪命令。要执行该命令,请将自定义 for
循环放入文件中,然后从 ~/.lldbinit
:
加载它
command script import path/to/mystack.py
编写 lldb 命令时,需要进行一些更改。这是一个结合了上述两种方法的示例:
import lldb
import re
REALM_PATTERN = re.compile("[Rr]ealm|RLM")
@lldb.command()
def mystack(debugger, command, ctx, result, _):
for frame in ctx.thread:
if not is_rx(frame) and not is_realm(frame):
print(f"{frame.idx}: {frame.name}", file=result)
def is_realm(frame):
return REALM_PATTERN.search(frame.name)
def is_rx(frame):
return "RxSwift/" in frame.line_entry.file.fullpath
当我使用 Realm 或 RxSwift 时出现异常,我得到这些我不关心的巨大调用堆栈,并且必须找到我的代码中的一两行。我只想在调用堆栈上显示来自目标 运行 的符号,而不是链接库。我怎样才能隐藏这些?
我不知道有什么方法可以过滤 Xcode 显示的内容,但您可能会发现 lldb 的 python 脚本很有帮助。至少有三种可能的方法来过滤堆栈:
- 框架名称
- 图书馆
- 来源路径
首先,要按名称过滤堆栈,可以使用正则表达式来检查函数名称。正则表达式可以匹配您要删除的帧,也可以匹配您想要保留的帧。从给定的堆栈跟踪中,我无法判断您想要保留哪些,因此我将演示如何删除 Realm 框架:
(lldb) script
import re
for frame in lldb.thread:
if not re.search("[Rr]ealm|RLM", frame.name):
print(f"{frame.idx}: {frame.name}")
按函数名称匹配并不总是理想的,它可能是一个很长或很复杂的正则表达式。如果你要过滤的库恰好是dynamic库或框架,那么最简单的方法就是按“模块”过滤:
(lldb) script
for frame in lldb.thread:
if frame.module.file.basename != "Realm":
print(f"{frame.idx}: {frame.name}")
第三个选项是按与每个帧关联的源路径进行过滤。我不知道这对 Realm 有用(这取决于调试信息),但我已经用 RxSwift 完成了。在此示例中,将不会打印源路径中具有 RxSwift/
的帧:
(lldb) script
for frame in lldb.thread:
if "RxSwift/" not in frame.line_entry.file.fullpath:
print(f"{frame.idx}: {frame.name}")
可重复使用的命令
可以结合使用这些方法来制作适合您的项目的堆栈跟踪命令。要执行该命令,请将自定义 for
循环放入文件中,然后从 ~/.lldbinit
:
command script import path/to/mystack.py
编写 lldb 命令时,需要进行一些更改。这是一个结合了上述两种方法的示例:
import lldb
import re
REALM_PATTERN = re.compile("[Rr]ealm|RLM")
@lldb.command()
def mystack(debugger, command, ctx, result, _):
for frame in ctx.thread:
if not is_rx(frame) and not is_realm(frame):
print(f"{frame.idx}: {frame.name}", file=result)
def is_realm(frame):
return REALM_PATTERN.search(frame.name)
def is_rx(frame):
return "RxSwift/" in frame.line_entry.file.fullpath