Xcode如何隐藏调用栈中的第三方调用

How to hide the third-party calls in the call stack in Xcode

当我使用 Realm 或 RxSwift 时出现异常,我得到这些我不关心的巨大调用堆栈,并且必须找到我的代码中的一两行。我只想在调用堆栈上显示来自目标 运行 的符号,而不是链接库。我怎样才能隐藏这些?

我不知道有什么方法可以过滤 Xcode 显示的内容,但您可能会发现 lldb 的 python 脚本很有帮助。至少有三种可能的方法来过滤堆栈:

  1. 框架名称
  2. 图书馆
  3. 来源路径

首先,要按名称过滤堆栈,可以使用正则表达式来检查函数名称。正则表达式可以匹配您要删除的帧,也可以匹配您想要保留的帧。从给定的堆栈跟踪中,我无法判断您想要保留哪些,因此我将演示如何删除 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