2016-08-03 8 views
6

Я знаю, что в Cocoa есть UncaughtExceptionHandler, но я ищу то же самое для Swift. то есть всякий раз, когда в приложении есть какая-либо ошибка/исключение, которое не попадает в локальную сеть из-за какой-либо ошибки, оно должно пузыриться полностью до объекта приложения верхнего уровня, где я должен умело обрабатывать его и соответствующим образом реагировать на пользователя.Неиспользованная ошибка/обработка исключений в Swift

Android имеет. Flex есть. Java есть. Удивление, почему Swift не хватает этой ключевой функции.

+0

NSSetUncaughtExceptionHandler доступен скоро: http://stackoverflow.com/questions/25441302/how-should-i-use-nssetuncaughtexceptionhandler-in-swift. Однако он улавливает только исключения Objective-C, а не ошибки времени выполнения Swift или ошибки throw. –

+0

Спасибо @MartinR за ваш быстрый ответ. Я знаю о NSSetUncaughtExceptionHandler, что он обрабатывает исключения Objective-C. Однако я ищу то же/подобное для Swift. –

+0

У Swift нет механизма для обнаружения ошибок во время выполнения. Я могу только догадываться о причине. Например, это не сработает с автоматическим подсчетом ссылок. Вы можете получить лучший ответ от разработчиков Swift в одном из списков рассылки на сайте swift.org. –

ответ

8

У Swift нет механизма, чтобы поймать все произвольные исключения во время выполнения. Причины объясняются в

на быстрых пользователей списка рассылки. Выдержка:

Swift сделал сознательный выбор, чтобы не включать исключения, через произвольных кадров стека не потому, что это было технически невозможно, но потому, что его создатели судить затраты слишком высоки.

Проблема заключается в следующем: если часть кода собирается выйти из-за ошибки , ее необходимо записать, чтобы обработать этот ранний выход. В противном случае будет ошибочно работать, не удалять память, не удается закрыть файл дескрипторы/сокеты/соединения с базой данных/что угодно, не удается освободить блокировки, и т. Д. На языке, таком как Java, для написания действительно безопасного кода требуется нелепое количество блоков try/finally. Вот почему никто этого не делает. Они выносят суждения о том, какие исключения у них есть , и какие ресурсы опасны для утечки, и только защищают свой код от этих конкретных ожидаемых условий. Затем происходит что-то непредвиденное, и их программа ломается.

Это еще хуже, в опорном подсчетом языке, как Swift, потому что правильно сбалансировать количество ссылок в присутствии исключений в основном требует, чтобы каждая функция включает неявное, наконец, блок , чтобы сбалансировать все сохраняющие отсчеты. Это означает, что компилятор должен генерировать много дополнительного кода при отсутствии вероятности того, что какой-либо вызов или другой вызывает исключение. Подавляющее большинство этого кода никогда, никогда не использовалось, но оно должно быть там, раздувая процесс.

Из-за этих проблем Свифт решил не поддерживать традиционные исключения ; вместо этого он позволяет вам делать ошибки в специально выделенных областях кода. Но, как следствие, это означает, что , если что-то пойдет не так в коде, который не может бросить, все, что можно сделать действительно сделать, чтобы предотвратить катастрофу. И в настоящее время, только вещь, которую вы можете разрушить, - это весь процесс.

Для получения дополнительной информации см

+1

Спасибо @MartinR ... Я обнаружил, что ребята Swift выгрузили бремя обработки каждого маленького или большого исключения и ошибок разработчикам «по дизайну». –

+1

Большое спасибо за обмен, теперь, по крайней мере, обоснование ясно для того, что казалось озадачивающим упущением. – Crashalot

+2

Все в порядке со мной, но мне по-прежнему нужно, по крайней мере, улавливать сигналы, чтобы я мог реализовать свой аварийный регистратор. Кажется, он не работает, хотя; принудительно распаковывает nil, выдает «EXC_BAD_INSTRUCTION», что я не могу поймать ни с исключением, ни с обработчиками сигналов ... –

5

Это код, я использую, чтобы регистрировать все исключения/ошибки. Log.error(with:) - это настраиваемая функция, где я храню трассировку стека, а также другую информацию. Thread.callStackSymbols - это массив строк и представляет собой трассировку стека.

NSSetUncaughtExceptionHandler { (exception) in 
     Log.error(with: Thread.callStackSymbols) 
    } 

    signal(SIGABRT) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
    signal(SIGILL) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 

    signal(SIGSEGV) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
    signal(SIGFPE) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
    signal(SIGBUS) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 

    signal(SIGPIPE) { (_) in 
     Log.error(with: Thread.callStackSymbols) 
    } 
+0

Большое спасибо, даже не знаю о функции сигнала (...) –

+1

Обратите внимание, что только «асинхронный сигнал безопасен» «функции безопасны для вызова из обработчиков сигналов. «printf» и связанные с ними функции не являются безопасными для асинхронного сигнала. –

+0

Где вы используете этот код? AppDelegate? главный? Я попытался добавить этот код в свое приложение без успеха. –