Swift 语言中的错误处理 [英] Error-Handling in Swift-Language

查看:21
本文介绍了Swift 语言中的错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Swift 的了解不多,但我注意到的一件事是没有例外.那么他们如何在 Swift 中进行错误处理呢?有没有人发现任何与错误处理相关的东西?

I haven't read too much into Swift but one thing I noticed is that there are no exceptions. So how do they do error handling in Swift? Has anyone found anything related to error-handling?

推荐答案

Swift 2 & 3

在 Swift 2 中,事情发生了一些变化,因为有一个新的错误处理机制,有点类似于异常,但在细节上有所不同.

Swift 2 & 3

Things have changed a bit in Swift 2, as there is a new error-handling mechanism, that is somewhat more similar to exceptions but different in detail.

如果函数/方法想表明它可能会抛出错误,它应该包含像这样的throws关键字

If function/method wants to indicate that it may throw an error, it should contain throws keyword like this

func summonDefaultDragon() throws -> Dragon

注意:没有指定函数实际可以抛出的错误类型.此声明只是声明该函数可以抛出实现 ErrorType 的任何类型的实例或根本不抛出.

为了调用函数,你需要使用 try 关键字,就像这样

In order to invoke function you need to use try keyword, like this

try summonDefaultDragon()

这一行通常应该像这样出现 do-catch 块

this line should normally be present do-catch block like this

do {
    let dragon = try summonDefaultDragon() 
} catch DragonError.dragonIsMissing {
    // Some specific-case error-handling
} catch DragonError.notEnoughMana(let manaRequired) {
    // Other specific-case error-handlng
} catch {
    // Catch all error-handling
}

注意:catch 子句使用了 Swift 模式匹配的所有强大功能,因此您在这里非常灵活.

如果您从本身用 throws 关键字标记的函数调用抛出函数,您可能决定传播错误:

You may decided to propagate the error, if your are calling a throwing function from a function that is itself marked with throws keyword:

func fulfill(quest: Quest) throws {
    let dragon = try summonDefaultDragon()
    quest.ride(dragon)
} 

或者,您可以使用 try? 调用 throwing 函数:

Alternatively, you can call throwing function using try?:

let dragonOrNil = try? summonDefaultDragon()

如果发生任何错误,您可以通过这种方式获得返回值或 nil.使用这种方式你不会得到错误对象.

This way you either get the return value or nil, if any error occurred. Using this way you do not get the error object.

这意味着您还可以将 try? 与有用的语句结合起来,例如:

Which means that you can also combine try? with useful statements like:

if let dragon = try? summonDefaultDragon()

guard let dragon = try? summonDefaultDragon() else { ... }

最后,您可以决定您知道错误实际上不会发生(例如,因为您已经检查了先决条件)并使用 try! 关键字:

Finally, you can decide that you know that error will not actually occur (e.g. because you have already checked are prerequisites) and use try! keyword:

let dragon = try! summonDefaultDragon()

如果该函数确实抛出了错误,那么您的应用程序将出现运行时错误,应用程序将终止.

If the function actually throws an error, then you'll get a runtime error in your application and the application will terminate.

为了抛出一个错误,你可以像这样使用 throw 关键字

In order to throw an error you use throw keyword like this

throw DragonError.dragonIsMissing

你可以抛出任何符合 ErrorType 协议的东西.对于初学者来说,NSError 符合此协议,但您可能希望使用基于枚举的 ErrorType,它使您能够对多个相关错误进行分组,可能带有附加数据,例如这个

You can throw anything that conforms to ErrorType protocol. For starters NSError conforms to this protocol but you probably would like to go with enum-based ErrorType which enables you to group multiple related errors, potentially with additional pieces of data, like this

enum DragonError: ErrorType {
    case dragonIsMissing
    case notEnoughMana(requiredMana: Int)
    ...
}

<小时>

新 Swift 2 和 Swift 之间的主要区别3 错误机制和Java/C#/C++风格的异常如下:


Main differences between new Swift 2 & 3 error mechanism and Java/C#/C++ style exceptions are follows:

  • 语法有点不同:do-catch + try + defer vs 传统的try-catch-finally 语法.
  • 异常处理在异常路径中的执行时间通常比在成功路径中长得多.Swift 2.0 错误并非如此,成功路径和错误路径的成本大致相同.
  • 必须声明所有错误抛出代码,而异常可能已从任何地方抛出.所有错误都是 Java 术语中的检查异常".但是,与 Java 不同的是,您没有指定可能抛出的错误.
  • Swift 异常与 ObjC 异常不兼容.您的 do-catch 块不会捕获任何 NSException,反之亦然,为此您必须使用 ObjC.
  • Swift 异常与 Cocoa NSError 返回false(对于Bool 返回函数)或nil 方法约定兼容code>(用于 AnyObject 返回函数)并传递带有错误详细信息的 NSErrorPointer.
  • Syntax is a bit different: do-catch + try + defer vs traditional try-catch-finally syntax.
  • Exception handling usually incurs much higher execution time in exception path than in success path. This is not the case with Swift 2.0 errors, where success path and error path cost roughly the same.
  • All error throwing code must be declared, while exceptions might have been thrown from anywhere. All errors are "checked exceptions" in Java nomenclature. However, in contrast to Java, you do not specify potentially thrown errors.
  • Swift exceptions are not compatible with ObjC exceptions. Your do-catch block will not catch any NSException, and vice versa, for that you must use ObjC.
  • Swift exceptions are compatible with Cocoa NSError method conventions of returning either false (for Bool returning functions) or nil (for AnyObject returning functions) and passing NSErrorPointer with error details.

作为一种额外的语法糖来简化错误处理,还有两个概念

As an extra syntatic-sugar to ease error handling, there are two more concepts

  • 延迟操作(使用 defer 关键字),让您实现与 Java/C#/etc 中的 finally 块相同的效果
  • guard 语句(使用 guard 关键字)让您编写的 if/else 代码比普通错误检查/信号代码少一点.
  • deferred actions (using defer keyword) which let you achieve the same effect as finally blocks in Java/C#/etc
  • guard statement (using guard keyword) which let you write little less if/else code than in normal error checking/signaling code.

运行时错误:

正如 Leandros 建议的处理运行时错误(如网络连接问题、解析数据、打开文件等),您应该像在 ObjC 中那样使用 NSError,因为 Foundation、AppKit、UIKit 等以这种方式报告他们的错误.所以与其说是语言,不如说是框架.

As Leandros suggests for handling runtime errors (like network connectivity problems, parsing data, opening file, etc) you should use NSError like you did in ObjC, because the Foundation, AppKit, UIKit, etc report their errors in this way. So it's more framework thing than language thing.

正在使用的另一种常见模式是分隔符成功/失败块,如 AFNetworking:

Another frequent pattern that is being used are separator success/failure blocks like in AFNetworking:

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

仍然是失败块频繁收到 NSError 实例,描述错误.

Still the failure block frequently received NSError instance, describing the error.

程序员错误:

对于程序员错误(如数组元素的越界访问、传递给函数调用的无效参数等),您在 ObjC 中使用了异常.Swift 语言似乎没有任何语言支持异常(如 throwcatch 等关键字).但是,正如文档表明它与 ObjC 在同一运行时运行,因此您仍然可以像这样抛出 NSExceptions:

For programmer errors (like out of bounds access of array element, invalid arguments passed to a function call, etc) you used exceptions in ObjC. Swift language does not seem to have any language support for exceptions (like throw, catch, etc keyword). However, as documentation suggests it is running on the same runtime as ObjC, and therefore you are still able to throw NSExceptions like this:

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

您无法在纯 Swift 中捕获它们,尽管您可以选择在 ObjC 代码中捕获异常.

You just cannot catch them in pure Swift, although you may opt for catching exceptions in ObjC code.

问题是您是否应该为程序员错误抛出异常,或者更确切地说是像 Apple 在语言指南中建议的那样使用断言.

The questions is whether you should throw exceptions for programmer errors, or rather use assertions as Apple suggests in the language guide.

这篇关于Swift 语言中的错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆