Игнорировать некоторые исключения, когда, используя все исключения останова в Xcode
У меня есть все исключения точка останова настроена в Xcode:
иногда Xcode останавливается на строке типа:
[managedObjectContext save:&error];
со следующим обратным следом:
но программа продолжает работать, как будто ничего не произошло, если вы нажмете кнопку Продолжить.
как я могу игнорировать эти "обычные" исключения, но все же остановить отладчик на исключениях в моем собственном коде?
(Я понимаю, что это происходит потому, что Core Data внутренне бросает и ловит исключения, и что Xcode просто выполняет мой запрос на приостановку программы всякий раз, когда возникает исключение. Однако я хочу игнорировать их, чтобы я мог вернуться к отладке своего собственного кода!)
модераторы: это похоже на "фильтрация точек останова исключения Xcode 4", но я думаю, что этот вопрос занимает слишком много времени, чтобы добраться до сути и не имеет никаких полезных ответов. Могут ли они быть связаны?
3 ответа:
я написал сценарий lldb, который позволяет выборочно игнорировать исключения Objective-C с гораздо более простым синтаксисом, и он обрабатывает как OS X, iOS Simulator, так и 32bit и 64bit 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 *) {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
С правильным путем, если вы сохранили его где-то еще.использование
- в Xcode добавьте точку останова, чтобы поймать все С исключения
- измените точку останова и добавьте команду отладчика с помощью следующей команды:
ignore_specified_objc_exceptions name:NSAccessibilityException className:NSSomeException
- это будет игнорировать исключения, где
NSException
-name
игрNSAccessibilityException
или-className
игрNSSomeException
это должно выглядеть это:
в вашем случае, вы должны использовать
ignore_specified_objc_exceptions className:_NSCoreData
см http://chen.do/blog/2013/09/30/selectively-ignoring-objective-c-exceptions-in-xcode/ для сценария и более подробной информации.
для исключений основных данных я обычно удаляю точку останова "все исключения" из Xcode и вместо этого:
- добавить символическую точку останова на
objc_exception_throw
- установите условие для точки останова в
(BOOL)(! (BOOL)[[(NSException *)$x0 className] hasPrefix:@"_NSCoreData"])
настроенная точка останова должна выглядеть примерно так:
это будет игнорировать любые частные исключения данных ядра (как определено именем класса с префиксом
_NSCoreData
), которые используются для контроля поток. Обратите внимание, что соответствующий регистр будет зависеть от целевого устройства / симулятора, в котором вы работаете. Взгляните на в этой таблице для справки.обратите внимание, что этот метод может быть легко адаптирован для других условий. Сложная часть заключалась в создании bool и nsexception casts, чтобы получить lldb счастливым с условием.
вот альтернативный быстрый ответ, когда у вас есть блок кода, например, библиотека 3-й части, которая выдает несколько исключений, которые вы хотите игнорировать:
- установите две точки останова, одну до и одну после исключения бросая блок кода, который вы хотите игнорировать.
- запустите программу, пока она не остановится на исключении, и введите "список точек останова" в консоль отладчика и найдите номер точки останова "все исключения", он должен выглядеть так это:
2: names = {'objc_exception_throw', '__cxa_throw'}, locations = 2 Опции: отключено 2.1: где = libobjc.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".
исключение все точки останова теперь будет включаться и выключаться, поэтому он активен только тогда, когда вам это нужно.