使用Xcode的“所有exception”断点时,请忽略某些exception

我有在Xcode中configuration的所有exception断点:

在Xcode断点痛苦中配置的异常断点的屏幕截图,配置为在抛出异常时发出声音

有时Xcode会停在一行,如:

[managedObjectContext save:&error]; 

跟着下面的回溯:

回溯显示NSPersistentStoreCoordinator在调用中抛出一个异常来保存:

但程序继续,如果您点击继续,就好像什么也没有发生。

我怎么能忽略这些“正常”的exception,但仍然有我的代码中的exception停止debugging器?

(我知道这是因为Core Data在内部引发并捕获exception,而且Xcode只是简单地遵守我的请求来暂停程序,但是,我想忽略这些,所以我可以回到debugging我自己的代码!)

版主:这与“Xcode 4exception断点过滤”类似,但我认为这个问题需要很长的时间来解决,并没有任何有用的答案。 他们能联系起来吗?

我写了一个lldb脚本,可以让你select性地忽略Objective-Cexception,并且可以处理OS X,iOS Simulator以及32位和64位ARM。

安装

  1. 把这个脚本放在~/Library/lldb/ignore_specified_objc_exceptions.py或者其他有用的地方。
 import lldb import re import shlex # This script allows Xcode to selectively ignore Obj-C exceptions # based on any selector on the NSException instance def getRegister(target): if target.triple.startswith('x86_64'): return "rdi" elif target.triple.startswith('i386'): return "eax" elif target.triple.startswith('arm64'): return "x0" else: return "r0" def callMethodOnException(frame, register, method): return frame.EvaluateExpression("(NSString *)[(NSException *)${0} {1}]".format(register, method)).GetObjectDescription() def filterException(debugger, user_input, result, unused): target = debugger.GetSelectedTarget() frame = target.GetProcess().GetSelectedThread().GetFrameAtIndex(0) if frame.symbol.name != 'objc_exception_throw': # We can't handle anything except objc_exception_throw return None filters = shlex.split(user_input) register = getRegister(target) for filter in filters: method, regexp_str = filter.split(":", 1) value = callMethodOnException(frame, register, method) if value is None: output = "Unable to grab exception from register {0} with method {1}; skipping...".format(register, method) result.PutCString(output) result.flush() continue regexp = re.compile(regexp_str) if regexp.match(value): output = "Skipping exception because exception's {0} ({1}) matches {2}".format(method, value, regexp_str) result.PutCString(output) result.flush() # If we tell the debugger to continue before this script finishes, # Xcode gets into a weird state where it won't refuse to quit LLDB, # so we set async so the script terminates and hands control back to Xcode debugger.SetAsync(True) debugger.HandleCommand("continue") return None return None def __lldb_init_module(debugger, unused): debugger.HandleCommand('command script add --function ignore_specified_objc_exceptions.filterException ignore_specified_objc_exceptions') 
  1. 将以下内容添加到~/.lldbinit

    command script import ~/Library/lldb/ignore_specified_objc_exceptions.py

    用正确的pathreplace~/Library/lldb/ignore_specified_objc_exceptions.py ,如果你把它保存在别的地方的话。

用法

  • 在Xcode中,添加一个断点来捕获所有的Objective-Cexception
  • 编辑断点并使用以下命令添加Debugger命令: ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
  • 这将忽略NSException -name匹配NSAccessibilityException-className匹配NSSomeException

它应该看起来像这样:

按照说明显示在Xcode中设置的断点的屏幕截图

在你的情况下,你可以使用ignore_specified_objc_exceptions className:_NSCoreData

有关脚本和更多详细信息,请参阅http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/

对于核心数据exception,我通常所做的是从Xcode中删除“所有exception”断点,而不是:

  1. objc_exception_throw上添加一个符号断点
  2. 将断点上的条件设置为(BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])

configuration的断点看起来应该像这样: 配置断点

这将忽略用于控制stream的任何专用核心数据exception(由类名前缀_NSCoreData )。 请注意,相应的寄存器将取决于您正在运行的目标设备/模拟器。请参阅此表以供参考。

请注意,这种技术可以很容易地适应其他条件。 棘手的部分是在制定BOOL和NSException投标,以获得满意的条件。

这里有一个替代的快速答案,当你有一个代码块,例如一个第三方库引发你想忽略的多个exception:

  1. 设置两个断点,一个在你想忽略的exception抛出代码块之前和之后一个。
  2. 运行程序,直到它停在一个exception处,然后在debugging器控制台中input“断点列表”,find“所有exception”断点的编号,它应该是这样的:

    2:names = {'objc_exception_throw','__cxa_throw'},locations = 2 Options:disabled 2.1:where = libobjc.A.dylib objc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0 2.2: where = libc++abi.dylib __cxa_throw,地址= 0x00007fff8d19fab7,未解决,命中计数= 0

  3. 这意味着它是断点2.现在在xcode中,编辑第一个断点(在exception抛出代码之前),并将操作更改为“debugger command”并键入“断点禁用2”(并设置“自动继续…”checkbox)。

  4. 在违规行之后的断点处执行相同的操作,并执行命令“断点使能2”。

所有的断点exception现在会打开和closures,所以它只在需要时才会激活。