我try 理解swift 2中的新错误处理.以下是我所做的:我首先声明了一个错误枚举:

enum SandwichError: ErrorType {
    case NotMe
    case DoItYourself
}

然后我声明了一个抛出错误的方法(不是异常,这是一个错误).以下是该方法:

func makeMeSandwich(names: [String: String]) throws -> String {
    guard let sandwich = names["sandwich"] else {
        throw SandwichError.NotMe
    }

    return sandwich
}

问题出在通话方.下面是调用此方法的代码:

let kitchen = ["sandwich": "ready", "breakfeast": "not ready"]

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
}

do行之后,编译器显示Errors thrown from here are not handled because the enclosing catch is not exhaustive.但在我看来,这是详尽的,因为SandwichError enum中只有两个病例.

对于常规的switch语句,Swift 可以理解,在处理每一个 case 时,它都是详尽的.

推荐答案

Swift 2错误处理模型有两个要点:彻底性和弹性.总之,它们归结为你的do/catch语句,需要捕捉每一个可能的错误,而不仅仅是你知道你可以抛出的错误.

请注意,您没有声明函数可以抛出什么类型的错误,只声明它是否抛出.这是一个0-1无穷大的问题:当有人定义一个函数供其他人(包括你future 的自己)使用时,你不想让你函数的每一个客户端都适应你函数实现中的每一个变化,包括它可能引发的错误.您希望调用函数的代码能够适应这种变化.

因为你的函数不能说它会抛出(或将来可能抛出)什么样的错误,所以捕获它错误的catch个块不知道它会抛出什么类型的错误.因此,除了处理已知的错误类型外,还需要使用universal catch语句处理不知道的错误类型——这样,如果函数在将来更改抛出的错误集,调用方仍将捕获其错误.

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
} catch let error {
    print(error.localizedDescription)
}

但我们不要就此止步.再想想这个弹性的 idea .按照你设计三明治的方式,你必须描述你使用三明治的每个地方的错误.这意味着,无论何时更改错误 case 集,都必须更改使用它们的每个位置...不是很有趣.

定义自己的错误类型背后的 idea 是让你集中处理类似的事情.您可以为自己的错误定义description种方法:

extension SandwichError: CustomStringConvertible {
    var description: String {
        switch self {
            case NotMe: return "Not me error"
            case DoItYourself: return "Try sudo"
        }
    }
}

然后,你的错误处理代码可以要求你的错误类型描述自己——现在,你处理错误的每个地方都可以使用相同的代码,也可以处理future 可能出现的错误情况.

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch let error as SandwichError {
    print(error.description)
} catch {
    print("i dunno")
}

这也为错误类型(或其扩展)提供了支持其他报告错误的方式的途径——例如,您可以在错误类型上有一个扩展,它知道如何为向iOS用户报告错误提供UIAlertController.

Swift相关问答推荐

如何在realityKit中反转USDZ动画

ARRaycast Query和前置摄像头(ARFaceTrackingConfiguration)

Result类型的初始值设定项失败?

将matchedGeometryEffect 应用于列表视图内的视图时,列表视图中的项目会受到影响 - SwiftUI

如何通过 Enum 属性使用新的 #Predicate 宏获取

ToolbarItem 包含在动画中但不应该包含在动画中

UIView.convert(_ point:to:)的意外行为

如何删除快速处理消息

如何让默认函数参数引用另一个函数参数?

为 ObservedObject 和 State 对象配置预览

用逻辑运算符保护让

Xcode:方法参数的代码完成

Swift - 如何更新多目录中的对象

在 ViewController 的 UICollectionView 中拉取刷新

iOS/Swift:如何检测 UITextField 上的touch 动作

Swift - 迭代 struct 对象时如何对其进行变异

不能从非开放类继承 swift

如何在 SwiftUI 中创建带有图像的按钮?

Facebook SDK 4.0 IOS Swift 以编程方式注销用户

强制打开已在同一行代码中 Select 性访问的变量是否安全?