合理,类型安全且灵活的实现,用于管理Swift App中的错误

上周,我开始重构一些与我现在正在使用的应用程序内的错误管理有关的代码。 我试图在互联网上找到一些实现示例,但是没有运气。 这就是为什么我在这里介绍自己的原因。

错误架构

在大多数情况下,应用程序仅用作前端,以向用户呈现信息。 因此,它与为它提供所需服务和数据的不同实体进行交互。 该实体是例如在线API,本地数据库或第三方框架。 他们所有人都会遇到错误。 我们应用程序的目标是捕获它们并做出相应反应,并在必要时通知用户。 为此,通常将错误与唯一的域ID(通常是字符串)和该域内的唯一代码(通常是整数)相关联,以识别错误。 因此错误架构如下所示:

在大多数情况下,错误还将包含其他关联数据,例如,如果发生错误,您将需要向用户显示本地化描述。 那么,您如何将所有这些信息反映到实现中? 更重要的是,如何使实施易于使用,组织合理,灵活且类型安全?

此外,最好在每个错误域内保修唯一的错误代码,并在编译时在我们的应用程序内保修唯一的域ID

一,错误的最低要求

我们可以使用协议指定它们:

我们还可以扩展该协议并添加一些有用的东西:

因为我们将使用具有原始整数值的枚举,所以我们添加了初始化程序和code属性的默认实现。 我们还添加了domain属性,因此我们可以访问错误的域ID,而无需访问其封闭类型(我们在协议中将其声明为静态)。

二,用于存储错误信息的类型

枚举类型是为此目的。 它还允许将原始值链接到每种情况,并保证此原始值是唯一的。 它们是存储错误代码的理想选择。 与ErrorProtocol一起,我们实现了一个基本错误,该错误在编译时为每个域强制使用唯一的错误代码。 域ID不能保证是唯一的(我没有在Swift语言中找到在编译时强制执行的工具)。

三,组织代码

为了组织代码,我选择镜像错误体系结构。 使用嵌套类型,我创建了一个伞形类型,用于存储所有不同的错误枚举(每个枚举与一个错误域匹配):

四,伞型的要求

给定一个域和一个代码,每种包装对应于多个错误域的枚举的伞型都应该能够返回错误。 我们可以通过使伞形类型符合以下协议来获得此功能:

在这种情况下,匹配函数负责探索伞型下每个枚举的域ID,并返回与域和代码匹配的错误。 由于Swift是一种类型安全的语言,因此我们需要为所有包含的枚举指定通用类型。 我们可以通过使用非通用协议作为具体类型来实现。 所有封闭的枚举都应符合此协议以及ErrorProtocol。

真实的例子

让我们看一个真实的例子。 现在,我正在一个名为AVO的应用程序中使用此实现(因此,如果您在即将发布的代码中看到AVO,现在您知道原因了)。

首先,我创建了一个满足我的需求的错误协议,该协议继承自ErrorProtocol并包含错误的本地化描述:

其次,我创建了一个伞形类型来存储所有错误枚举。 我使它符合ErrorUmbrellaProtocol并实现匹配功能:

然后添加错误枚举(在这种情况下为两个域,即内部应用程序错误和服务器错误):

现在我们可以如下使用所有这些。 例如,假设我们从服务器获取域ID和错误代码:

为了检查我们收到的确切错误,(如果您要做的不只是显示本地化的错误说明,还可以通过几种方法来做到这一点:

而且将错误信息发送到应用之外也非常容易:

干净吗? ^^