swift uncaughtexceptionhandler

Manejo de errores/excepciones no detectados en Swift



uncaughtexceptionhandler (3)

Sé que hay un UncaughtExceptionHandler en Cocoa, sin embargo, estoy buscando lo mismo para Swift. es decir, siempre que haya algún error / excepción en la aplicación que no se encuentre localmente allí debido a algún error, debería aparecer en el objeto de la aplicación de nivel superior donde debería poder manejarlo con gracia y responder al usuario de manera adecuada.

Android tiene. Flex tiene. Java tiene. Preguntándose por qué a Swift le falta esta característica clave.


Este es el código que uso para registrar todas las excepciones / errores. Log.error(with:) es una función personalizada donde Log.error(with:) el seguimiento de la pila, junto con otra información. Thread.callStackSymbols es una matriz de cadenas y representa el seguimiento de la pila.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool { 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) } return true }


Swift no tiene ningún mecanismo para capturar todas las excepciones de tiempo de ejecución arbitrarias. Las razones se explican en

en el foro de usuarios rápidos. Extraer:

Swift tomó una decisión consciente de no incluir excepciones lanzadas a través de marcos de pila arbitrarios no porque fuera técnicamente imposible, sino porque sus diseñadores consideraron que los costos eran demasiado altos.

El problema es este: si una pieza de código va a salir temprano debido a un error, debe escribirse para manejar esa salida temprana. De lo contrario, se comportará mal: no se desasignará la memoria, no se cerrarán los identificadores de archivo / los sockets / las conexiones de la base de datos / lo que sea, no se liberarán los bloqueos, etc. bloques Por eso nadie lo hace. Hacen juicios sobre qué excepciones es probable que vean y qué recursos son peligrosos para filtrar, y solo protegen su código contra esas condiciones específicas anticipadas. Entonces sucede algo imprevisto y su programa se rompe.

Esto es aún peor en un lenguaje de conteo de referencias como Swift porque balancear correctamente los conteos de referencia en presencia de excepciones básicamente requiere que cada función incluya un bloque finalmente implícito para balancear todos los conteos retenidos. Esto significa que el compilador tiene que generar un montón de código adicional en caso de que alguna llamada u otra arroje una excepción. La gran mayoría de este código nunca se usa, pero tiene que estar allí, hinchando el proceso.

Debido a estos problemas, Swift decidió no admitir excepciones tradicionales; en cambio, solo le permite lanzar errores en regiones de código especialmente marcadas. Pero como corolario, eso significa que, si algo sale realmente mal en un código que no puede arrojarse, todo lo que realmente puede hacer para evitar un desastre es un bloqueo. Y actualmente, lo único que puede bloquear es todo el proceso.

Para más información, ver


enter code here

import UIKit import CoreData

clase ViewController: UIViewController {

@IBOutlet weak var lgnusername: UITextField! @IBOutlet weak var lgnpassword: UITextField!

resultado var = NSArray ()

override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } @IBAction func loginaction(_ sender: Any) { let app = UIApplication.shared.delegate as! AppDelegate let context = app.persistentContainer.viewContext let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Login") let searchString = self.lgnusername.text let searcghstring2 = self.lgnpassword.text request.predicate = NSPredicate (format: "username == %@", searchString!) do { let result = try context.fetch(request) if result.count > 0 { let n = (result[0] as AnyObject).value(forKey: "username") as! String let p = (result[0] as AnyObject).value(forKey: "userpassword") as! String print("p,n",n,p) if (searchString == n && searcghstring2 == p) { let UserDetailsVc = self.storyboard?.instantiateViewController(withIdentifier: "userViewController") as! userViewController //UserDetailsVc.myStringValue = lgnusername.text self.navigationController?.pushViewController(UserDetailsVc, animated: true) } else if (searchString == n || searcghstring2 == p) { // print("password incorrect ") let alertController1 = UIAlertController (title: "no user found ", message: "password incorrect ", preferredStyle: UIAlertControllerStyle.alert) alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) present(alertController1, animated: true, completion: nil) } } else { let alertController1 = UIAlertController (title: "no user found ", message: "invalid username ", preferredStyle: UIAlertControllerStyle.alert) alertController1.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) present(alertController1, animated: true, completion: nil) print("no user found") } } catch { print("error") } }

}