В Objective-C я вызываю метод NSSetUncaughtExceptionHandler(&exceptionHandler)
для регистрации исключений. Как он называется в Swift?
Как использовать NSSetUncaughtExceptionHandler в Swift
Ответ 1
Update
С Swift 2 вы можете передавать функции Swift и замыкания в качестве указателя функции C. См. ответ Martin R ниже.
Оригинальный ответ
Вы не можете, начиная с Xcode 6 beta 6.
Swift поддерживает прокрутку указателей функций, но их обрабатывают почти как непрозрачные указатели. Вы не можете ни определять указатель функции C функции Swift, ни вызывать вызов функции C в Swift.
Это означает, что вы вызываете NSSetUncaughtExceptionHandler()
из Swift, но обработчик должен быть реализован в Objective-C. Вам нужен заголовочный файл:
volatile void exceptionHandler(NSException *exception);
extern NSUncaughtExceptionHandler *exceptionHandlerPtr;
и в реализации вам нужно что-то вроде этого:
volatile void exceptionHandler(NSException *exception) {
// Do stuff
}
NSUncaughtExceptionHandler *exceptionHandlerPtr = &exceptionHandler;
После импорта файла заголовка в заголовке моста Swift вы можете настроить обработчик исключений, как обычно:
NSSetUncaughtExceptionHandler(exceptionHandlerPtr)
Ответ 2
Начиная с Swift 2 (Xcode 7), вы можете передавать функции/замыкания Swift параметрам, принимающим указатель на функцию C. Из примечаний к выпуску Xcode 7:
Встроенная поддержка указателей на функции C: функции C, которые принимают аргументы указателя на функцию, могут вызываться с использованием замыканий или глобальных функций, с ограничением на то, что замыкание не должно захватывать ни один из его локального контекста.
Итак, это компилируется и работает:
func exceptionHandler(exception : NSException) {
print(exception)
print(exception.callStackSymbols)
}
NSSetUncaughtExceptionHandler(exceptionHandler)
Или с "встроенным" закрытием:
NSSetUncaughtExceptionHandler { exception in
print(exception)
print(exception.callStackSymbols)
}
Это делает то же самое, что и соответствующий код Objective C: он перехватывает необработанные NSException
. Так что это будет поймано:
let array = NSArray()
let elem = array.objectAtIndex(99)
ПРИМЕЧАНИЕ: - Он не перехватывает никаких ошибок Swift 2 (из throw
) или ошибок времени выполнения Swift, поэтому он не перехватывается:
let arr = [1, 2, 3]
let elem = arr[4]
Ответ 3
Ошибка, которую вы можете увидеть при повторном открытии следующего приложения таким образом.
Этот код для swift 4. Добавьте в didFinishLaunchingWithOptions()
:
NSSetUncaughtExceptionHandler { exception in
print("Error Handling: ", exception)
print("Error Handling callStackSymbols: ", exception.callStackSymbols)
UserDefaults.standard.set(exception.callStackSymbols, forKey: "ExceptionHandler")
UserDefaults.standard.synchronize()
}
А код добавь в fistViewController viewLoad()
// ERROR ExceptionHandler
if let exception = UserDefaults.standard.object(forKey: "ExceptionHandler") as? [String] {
print("Error was occured on previous session! \n", exception, "\n\n-------------------------")
var exceptions = ""
for e in exception {
exceptions = exceptions + e + "\n"
}
AlertFunctions.messageType.showYesNoAlert("Error was occured on previous session!", bodyMessage: exceptions, {
}, no: {
UserDefaults.standard.removeObject(forKey: "ExceptionHandler")
UserDefaults.standard.synchronize()
})
}
РЕДАКТИРОВАТЬ: код работает. Но вам нужно заново открыть приложение после ошибки.
Ответ 4
Свифт 5:
1. Добавьте этот метод в AppDelegate:
func storeStackTrace() {
NSSetUncaughtExceptionHandler { exception in
print(exception)
// do stuff with the exception
}
}
2. Вызвать этот метод из didFinishLaunchingWithOptions и вызвать исключение сразу после
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
storeStackTrace()
let exception = NSException(name: NSExceptionName(rawValue: "arbitrary"), reason: "arbitrary reason", userInfo: nil)
exception.raise()
}
3. Следите за выводом на консоль, он немедленно распечатает исключение, которое вы только что вызвали, начиная с указанной вами причины.