Как поймать сбой 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)")

    }