「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
Swift 标准库的 Result 类型使我们能够使用单一、统一的类型来表达给定操作的结果——无论是成功还是失败。 让我们看看 Result 在哪些情况下可能有用,以及在开始使用该类型时需要牢记的一些提示和技巧。
虽然有许多不同的方法可以对 Result 类型进行建模,但 Swift 标准库中内置的一种方法被声明为一个泛型枚举,它对结果可能包含的成功值以及任何错误都进行了强类型化。 遭遇。 它看起来像这样:
正如上面的声明所示,我们可以使用 Result 来表示任何成功/失败的组合,只要 Failure 类型符合 Swift 的 Error 协议。 那么在实践中我们如何使用上述类型,这样做有什么好处呢?
作为一个例子,让我们看一下 URLSession,以及它最常用的 API 之一——它使用基于闭包的设计以异步方式返回网络请求的各种结果:
尽管 URLSession 多年来已经发展了很多,并且拥有一套功能强大的 API,但准确地决定如何处理网络调用的结果有时会有点棘手——因为就像上面的示例所示,数据和 潜在的错误结果作为可选参数传递到我们的闭包中——这反过来又要求我们在每次进行网络调用时解开每个值。
让我们看看使用 Result 如何帮助我们解决这个问题。 我们将从使用新 API 扩展 URLSession 开始,该 API 将 Result<Data, Error> 值传递到其完成处理程序中,而不是一组选项。 为了实现这一点,我们将解开标准 API 提供给我们的可选参数(类似于我们上面所做的),以构造我们的 Result —— 如下所示:
如果我们现在回到之前的调用站点并更新它以使用我们的新 API,我们可以看到我们的代码变得更加清晰——因为我们现在可以为成功和失败情况编写完全独立的代码路径,就像这样 :
关于我们上面使用 Result 的方式的一个有趣细节是,我们将它的 Failure 类型简单地指定为 Error。 这意味着任何错误都可以传递到我们的结果中,这反过来又限制了我们在调用站点进行更具体的错误处理的选项(因为我们没有要处理的潜在错误的详尽列表)。 虽然在直接使用系统 API 时很难改变,而系统 API 反过来又会引发任何错误——当我们构建更具体的抽象形式时,我们通常可以为其设计更统一的错误 API。
例如,假设我们正在构建一个非常简单的图像加载器,它可以让我们通过网络加载图像,再次使用 URLSession。 但在我们开始实际实现加载器本身之前,让我们首先定义一个枚举,列出它可能遇到的所有潜在错误。 目前,我们只有两种情况——发生网络错误,或者我们下载的数据无效:
然后,在构建我们的图像加载器时,我们现在可以使用上述错误类型专门化 Result ——这反过来又使我们能够向我们的调用站点发送更丰富的错误信息:
然后,上述设计使我们能够在使用我们的图像加载器时以更精细的方式处理每个潜在的错误,例如: