我在Xcode中配置了一个All Exceptions断点:
有时Xcode会停在以下一行:
[managedObjectContext save:&error];
带有以下回溯:
但如果单击“继续”,程序将继续运行,好像什么也没发生。
如何忽略这些“正常”异常,但仍然让调试器在我自己的代码中停止异常?
(我知道发生这种情况是因为Core Data内部抛出并捕获异常,并且Xcode只是在抛出异常时我的请求暂停程序。但是,我想忽略这些,所以我可以回到调试我自己的代码!)
主持人:这类似于"Xcode 4 exception breakpoint filtering",但我认为这个问题需要很长时间才能解决问题并且没有任何有用的答案。它们可以链接吗?
答案 0 :(得分:86)
对于核心数据异常,我通常做的是从Xcode中删除“All Exceptions”断点,而不是:
objc_exception_throw
(BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])
配置的断点应如下所示:
这将忽略用于控制流的任何私有Core Data异常(由类名称为前缀_NSCoreData
确定)。请注意,相应的寄存器将取决于您运行的目标设备/模拟器。请查看this table以供参考。
请注意,此技术可以轻松适应其他条件。棘手的部分在于制作BOOL和NSException强制转换以使lldb对条件感到满意。
答案 1 :(得分:38)
我编写了一个lldb脚本,它允许您使用更简单的语法选择性地忽略Objective-C异常,并且它可以处理OS X,iOS模拟器以及32位和64位ARM。
~/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')
将以下内容添加到~/.lldbinit
:
command script import ~/Library/lldb/ignore_specified_objc_exceptions.py
如果您将~/Library/lldb/ignore_specified_objc_exceptions.py
保存在其他地方,请使用正确的路径替换ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
。
NSException
-name
NSAccessibilityException
匹配-className
或NSSomeException
匹配ignore_specified_objc_exceptions className:_NSCoreData
看起来应该是这样的:
在您的情况下,您将使用{{1}}
有关脚本和更多详细信息,请参阅http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/。
答案 2 :(得分:10)
如果您有一段代码,可以选择以下快速解答:第三方库,它会抛出您想要忽略的多个异常:
2:names = {' objc_exception_throw',' __ cxa_throw'},locations = 2 选项:禁用 2.1:where = libobjc.A.dylib
objc_exception_throw, address = 0x00007fff8f8da6b3, unresolved, hit count = 0 2.2: where = libc++abi.dylib
__ cxa_throw,address = 0x00007fff8d19fab7,unresolved,hit count = 0
这意味着它是断点2.现在在xcode中,编辑第一个断点(在抛出异常代码之前)并将操作更改为“调试器命令”。并输入'断点禁用2' (并设置'自动继续...'复选框)。
对违规行后的断点执行相同操作,并使用命令'断点启用2'。
所有断点异常现在将打开和关闭,因此它只在您需要时才会激活。