Как поймать сбой Swift и сделать некоторые каротажи
В Objective-C NSSetUncaughtExceptionHandler
может зарегистрировать некоторую функциональность, чтобы сделать последнюю запись журнала об исключении.
Это не ломается от Swift.
Можно ли сделать что-то подобное на глобальном уровне в Свифт? Например. выполните некоторые протоколирования, если в Swift произошел сбой, например принудительное разворачивание нулевого параметра.
В частности, я делаю утилиту для регистрации сетевого трафика в приложении, и я хотел бы очистить мои данные в памяти на диск, если произойдет сбой.
Ответы
Ответ 1
NSSetUncaughtExceptionHandler
работает только с NSExceptions. Смотрите этот ТА ответ для блестящего объяснения.
Чтобы отловить ошибки времени выполнения Swift, реализуйте обработчик сигнала для SIGTRAP
. Насколько я знаю, код Swift прекратит работу программы с типом исключения SIGTRAP
, если обнаружит непредвиденное состояние во время выполнения, т.е. только SIGTRAP
полезен для обнаружения ошибок Swift, остальные как SIGSEGV
, SIGBUS
, SIGILL
не работает.
Я нашел эту информацию в этой яблочной ссылке.
Если ваш код представляет собой смесь Objective-C и Swift, то реализуйте NSSetUncaughtExceptionHandler
и обработчик сигналов для обработки сбоев.
Для понимания и реализации обработки сигналов см. эту ссылку.
Надеюсь это поможет.
Ответ 2
На ваши вопросы есть несколько аспектов, позвольте мне попытаться ответить на них:
-
NSSetUncaughtExceptionHandler
только ловит неперехваченные исключения, которые являются лишь небольшим подмножеством возможных сбоев.
- Исключения в Objective-C определены как фатальные, и не рекомендуется их ловить, а еще больше не рекомендуется запускать любой неасинхронный безопасный код, который включает в себя любые Objective-C и код Swift
- Чтобы поймать сбои, вам нужно настроить обработчики сигналов, а затем выполнить только безопасный асинхронный код во время сбоя, который является лишь небольшим подмножеством C. Особенно вы не можете выделять новую память во время сбоя вообще.
- Помните, когда ваше приложение разбилось, оно находится в очень неустойчивом коде, а ссылки на объекты или переменные могут указывать на что-то совершенно неожиданное. Таким образом, вы действительно ничего не должны делать во время сбоя.
- Лучший способ с открытым исходным кодом для работы с авариями использует PLCrashReporter, который также предоставляет метод для вызова кода во время сбоя. Но опять же, это должно быть асинхронно.
К вашему конкретному сценарию: вы не должны этого делать, а не пытаться. Это может привести к повреждению данных пользователя или к потере данных. Приложение сильно сработало с серьезными проблемами, скорее устранить проблему.
Ответ 3
NSSetUncaughtExceptionHandler(&HandleException);
signal(SIGABRT, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGPIPE, SignalHandler);
Это будет работать в большинстве ситуаций. Но я также пытаюсь найти способ поймать все сбои. Ну, если вы подойдете + нажмите на эти сигналы, чтобы увидеть документы, вы обнаружите, что существует более 20 видов сигналов, что я сделал, это сигнал (,) всех самых разных сигналов. Кажется, что это работает, но, возможно, еще может произойти сбой.
Ответ 4
в Swift 5 вы можете справиться с крахом приложения следующим образом:
NSSetUncaughtExceptionHandler { (exception) in
let stack = exception.callStackReturnAddresses
print("Stack trace: \(stack)")
}