Uncaught Error/Exception Handling in Swift

怎甘沉沦 提交于 2019-11-26 03:26:53

问题


I know there is an UncaughtExceptionHandler in Cocoa, However I am looking for same thing for Swift. i.e. whenever there is any error/exception in application which is not caught locally there due to any mistake, it should bubble all the way to the top level application object where I should be able to gracefully handle it and respond to user appropriately.

Android has it. Flex has it. Java has it. Wondering why Swift is missing this key feature.


回答1:


Swift has no mechanism to catch all arbitrary runtime exceptions. The reasons are explained in

  • [swift-users] "business applications market" flame

in the swift-users forum. Extract:

Swift made a conscious choice not to include exceptions thrown through arbitrary stack frames not because it was technically impossible, but because its designers judged the costs to be too high.

The problem is this: if a piece of code is going to exit early because of an error, it has to be written to handle that early exit. Otherwise it will misbehave—fail to deallocate memory, fail to close file handles/sockets/database connections/whatever, fail to release locks, etc. In a language like Java, writing truly exception-safe code requires a ridiculous quantity of try/finally blocks. That's why nobody does it. They make judgements about which exceptions they're likely to see and which resources are dangerous to leak, and only protect their code against those specific anticipated conditions. Then something unforeseen happens and their program breaks.

This is even worse in a reference-counted language like Swift because correctly balancing the reference counts in the presence of exceptions basically requires every function to include an implicit finally block to balance all the retain counts. This means the compiler has to generate lots of extra code on the off chance that some call or another throws an exception. The vast majority of this code is never, ever used, but it has to be there, bloating the process.

Because of these problems, Swift chose not to support traditional exceptions; instead, it only allows you to throw errors in specially-marked regions of code. But as a corollary, that means that, if something goes really wrong in code that can't throw, all it can really do to prevent a disaster is crash. And currently, the only thing you can crash is the entire process.

For more information, see

  • Error Handling Rationale and Proposal



回答2:


This is the code I use to log all exceptions/errors. Log.error(with:) is a custom function where I store the stack trace, along with other info. Thread.callStackSymbols is an array of strings and represents the stack trace.

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
}



回答3:


enter code here

import UIKit import CoreData

class ViewController: UIViewController {

@IBOutlet weak var lgnusername: UITextField!

@IBOutlet weak var lgnpassword: UITextField!

var result = 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")
    }
}

}



来源:https://stackoverflow.com/questions/38737880/uncaught-error-exception-handling-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!