How get the list of errors thrown by a function?

前端 未结 3 1504
太阳男子
太阳男子 2020-12-03 21:34

With Swift now some functions are marked with throws, and this force the developers to call the function inside a do - try catch block. But how the

相关标签:
3条回答
  • 2020-12-03 21:50

    When the Swift docs says a function throws, they mean that it throws an ErrorType (in Cocoa APIs usually an NSError), not an exception.

    Consider the following do-try-catch flow for NSFileManager's createDirectoryAtPath:

    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
    
    do {
        try NSFileManager.defaultManager().createDirectoryAtPath(documentsPath, withIntermediateDirectories: false, attributes: nil)
    } catch { 
        // 'error' variable automatically populated
        print(error)
        print(error.dynamicType)
    }
    

    createDirectoryAtPath will fail because the documents directory already exists. Logging the dynamicType of the error shows that it is in fact an NSError object:

    Error Domain=NSCocoaErrorDomain Code=516 "The file “Documents” couldn’t be saved in the folder “35B0B3BF-D502-4BA0-A991-D07568AB87C6” because a file with the same name already exists." UserInfo={NSFilePath=/Users/jal/Library/Developer/CoreSimulator/Devices/E8A35774-C9B7-42F0-93F1-8103FBBC7118/data/Containers/Data/Application/35B0B3BF-D502-4BA0-A991-D07568AB87C6/Documents, NSUnderlyingError=0x7fa88bd14410 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}
    
    NSError
    

    In order to see the different types of errors a function can throw, you would have to examine the error for information to determine the type of error thrown, and how to handle each error. In the case of NSError this would be its domain, code, and description.

    In this particular case, a directory already exists at that path, so the file manager cannot create a new directory. An example of another reason why this operation could fail would be if the file manager did not have write access. That would be error code 256.

    0 讨论(0)
  • 2020-12-03 21:57

    You write a pattern after catch to indicate what errors that clause can handle.

    do {
        try expression
        statements
    } catch pattern 1 {
        statements
    } catch pattern 2 where condition {
        statements
    }
    

    See section Handling Errors Using Do-Catch of Swift Programming Language

    0 讨论(0)
  • 2020-12-03 22:03

    I had the exact same question as the OP. Since no one really answered the question as he asked (and I as well), here goes my contribution.

    In Swift 3 and Xcode 8.3.3 you would do as follows to treat the individual exceptions. Below I will give you an example with FileManager.

    First you will have only one catch block to catch whatever error the method throws at you. Then you will cast that error as an NSError. Contrary to the Error protocol in Swift, NSError is a REAL error class. Then you can extract that error's code in a switch statement. You will have to know what domain that method throws error from and then find the error codes in the appropriate header file.

    In my example below, the file related errors are thrown in the NSCocoaErrorDomain and these errors codes are defined/listed in Foundation/FoundationErrors.h. In my computer, they are located at

    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Foundation.framework/Versions/C/Headers/FoundationErrors.h
    

    for macOS apps and at

    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/Foundation.framework/Headers/
    

    for iPhone apps.

    So here is an example:

    let home = FileManager.default.homeDirectoryForCurrentUser
    let file = home.appendingPathComponent("file")
    do {
        let loadedString = try String(contentsOf: file)
    }
    catch {
        let realError = error as NSError // As weird as it looks, Xcode actually wants this forced conversion
        print(realError.localizedDescription)
        switch realError.code {
        case 257: // No permission
            handleNoPermission()
        case 260: // File not found
            handleFileNotFound()
        default:
            handleUndefinedError()
        }
    }
    

    The .localizedDescription contains a user friendly message in your user's language about that error. If file is not found above it prints: The file “file” couldn’t be opened because there is no such file. in English. It is meant to be used directly in the error dialogs you present to your user.

    You may also find more information about what error is thrown by each domain here: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorObjectsDomains/ErrorObjectsDomains.html

    0 讨论(0)
提交回复
热议问题