Swift错误处理

Swift错误处理

hudson 译 原文

处理应用程序中的错误和意外值可以说与处理有效结果一样重要。让我们看看一些关键技术,这些技术可以帮助我们在代码中遇到错误时提供更好的用户体验。

Swift提供了一种使用Error协议定义和处理错误的原生方法。符合它不需要添加任何特定的属性或方法,因此我们可以轻松地使任何类型符合它------例如下面的枚举,该枚举包含一些在验证字符串值时可能遇到的不同错误:

swift 复制代码
enum ValidationError: Error {
    case tooShort
    case tooLong
    case invalidCharacterFound(Character)
}

使用上述错误枚举,我们现在可以编写一个简单的函数,验证给定的username用户名不是太长或太短,并且它不包含任何非字母字符。为此,我们将把函数标记为能够使用throws抛出错误,并在不满足验证要求的情况下使用throw关键字触发错误------像这样:

swift 复制代码
func validate(username: String) throws {
    guard username.count > 3 else {
        throw ValidationError.tooShort
    }

    guard username.count < 15 else {
        throw ValidationError.tooLong
    }

    for character in username {
        guard character.isLetter else {
            throw ValidationError.invalidCharacterFound(character)
        }
    }
}

由于用throws标记了上述函数, 现在需要在其调用前加上try关键字------这反过来又迫使我们处理从它抛出的任何错误(或使用try?将其返回值转换为可选值)。例如,在这里,使用上述函数来验证用户刚刚选择的用户名,如果验证通过(没有抛出错误),则继续将该用户名提交给服务器------否则使用UILabel显示遇到的错误:

swift 复制代码
func userDidPickName(_ username: String) {
    do {
        try validate(username: username)
        // If we reach this point in the code, then it means
        // that no error was thrown, and the validation passed.
        submit(username)
    } catch {
        // The variable 'error' is automatically available
        // inside of 'catch' blocks.
        errorLabel.text = error.localizedDescription
    }
}

但是,如果我们以无效的用户名作为输入(如"john-sundell")运行上述代码,errorLable中将显示一条非常晦涩的错误消息:

The operation couldn't be completed. (App.ValidationError error 0.)

上述信息会让用户感到困惑。既没有可行动的信息,还向用户暴露了实现细节(例如错误类型的名称)。

解决方案是启用错误类型本地化。为此,扩展ValidationError以符合LocalizedError,这是Error协议的专门版本。通过实现其errorDescription属性------我们现在可以为每个错误情况返回适当的本地化消息:

swift 复制代码
extension ValidationError: LocalizedError {
    var errorDescription: String? {
        switch self {
        case .tooShort:
            return NSLocalizedString(
                "Your username needs to be at least 4 characters long",
                comment: ""
            )
        case .tooLong:
            return NSLocalizedString(
                "Your username can't be longer than 14 characters",
                comment: ""
            )
        case .invalidCharacterFound(let character):
            let format = NSLocalizedString(
                "Your username can't contain the character '%@'",
                comment: ""
            )

            return String(format: format, String(character))
        }
    }
}

随着上述更改到位,之前的验证错误现在将以更友好的方式显示:

Your username can't contain the character '-'

好多了👍。好消息是,在处理异步错误时,我们也可以应用许多相同的技术。到目前为止,我们只以完全同步的方式处理错误和抛出函数------上面使用的do、try、catch模式对此非常出色------但当涉及到异步代码时,错误通常会传递给一个完成处理程序,而不是抛出。

例如,假设我们想使validate函数异步------也许能够进行网络绑定验证,或者在后台线程上执行更复杂的规则。为此需要转换函数签名,如下:

swift 复制代码
func validate(username: String,
              then handler: @escaping (ValidationError?) -> Void) {
    ...
}

由于错误现在作为可选值传递给handler闭包,我们必须使用略微不同的策略来捕获它们。谢天谢地,这只是一个解包可选值的问题,并使用相同的localizedDescription属性来访问本地化的错误消息------而不是使用catch块:

swift 复制代码
func userDidPickName(_ username: String) {
    validate(username: username) { error in
        if let error = error {
            errorLabel.text = error.localizedDescription
        } else {
            submit(username)
        }
    }
}

花一点额外的时间为应用程序添加适当的错误处理,可以真正提高其感知质量。没有人喜欢被卡在屏幕上,上面有一条晦涩的错误信息,该错误信息没有真正说明什么,也没有提供任何形式的建议来纠正错误。通过在错误类型中添加本地化,以及一些代码来处理和显示这些错误,可以让用户感觉更好------即使出了问题。

谢谢你的阅读!

相关推荐
东坡肘子12 小时前
iPhone Duo 带来的机遇与挑战 -- 肘子的 Swift 周报 #153
人工智能·swiftui·swift
闲云自留地2 天前
云平台存储管理员:Cinder 创建挂载卷 + Swift 分布式存储原理
分布式·wpf·swift
2501_915909064 天前
SwiftUI 和 UIKit 怎么选?两代 UI 框架的适用范围
vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_915918414 天前
在Windows10上使用VSCode和Code Runner搭建Swift开发环境详细步骤
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
用户468104557245 天前
Swift 异步与并发
swift
安当加密03015 天前
PCI DSS 4.0与SWIFT CSP双合规:银行收单与跨境支付HSM部署实战
swift·hsm·密钥管理·pci dss·双合规
麒麟马6 天前
Swift 扩展归纳---Array (一)
ios·swift
2501_915106326 天前
Swift 4开发环境设置教程:xCode安装与Playground入门
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子8 天前
当 Mac mini 的价格不再 mini -- 肘子的 Swift 周报 #152
人工智能·swiftui·swift
2501_9151063211 天前
第一次开发 iPhone App,可能碰到的问题,解决办法
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程