只是我的类型! — Swift中的自定义类型和错误处理

在坐下来编写代码之前,重要的是解决您需要处理的第一个错误,而不是try -ing。

阅读文档或花时间学习错误处理并不是大多数人都觉得有趣的时光。 起初绝对不是我的。 但是,在探索了有关该主题的一些教程和当代文献之后,我发现在构造自定义类型以处理错误方面有一定的赞赏。

无论您是终身使用的Swift开发人员,还是刚入门的人,都有可能听说过Functional Programming

函数式Swift是一个很棒的资源,它是Swift中函数式编程的简介。 尽管此资源着重介绍了许多很棒的主题,但我发现有关枚举Swift错误的部分在我的项目中特别有用。 这篇文章将带您浏览一些受这些部分启发的示例。

以下示例可在我的演示存储库中的操场上找到。 随意克隆或下载仓库,然后继续!

我确定我们已经编写了所有方法来检查数组字典中的某些值。 这些容器类型是Swift标准库的一部分,是iOS开发不可或缺的一部分。 在下面的示例中,我们将优化一种方法,该方法仅使用个人的memberName来检索团队成员的数量。 但是,要获取团队成员的数量,需要先查找团队。 构建此方法的合理方法可能如下所示:

使用可选的返回类型

  func numberOfTeamMembers(memberName:String)->整数?  {卫队让team = teamNames [memberName]否则{return nil} 
后卫让号= teamMembers [team] else {return nil}
返回号码
}

然后,我们可以像下面这样在我们的代码中调用此方法:

let someLookup = numberOfTeamMembers(memberName: "Tommy")

还不错吧? 我们的numberOfTeamMembers(memberName:)方法将返回可选的Int? 如果查找成功。 否则,如果其中一项检查失败, someLookup将包含nil 。 尽管这似乎是解决问题的一种合理方法,但我们对查找失败的原因一无所知。 换句话说,如果上述方法返回nil ,那么我们将不知道哪些检查没有通过。 对于更复杂的方法,在跟踪查找错误的来源时可能会出现问题。

numberOfTeamMembers(memberName:)方法的缺点之一在于其返回类型Int? 。 如果我们可以创建自己的返回类型怎么办? 具体来说,如果查找成功,则可以返回Int的类型,如果查找失败,则可以返回详细的错误。 为此,我们可以尝试如下操作:

 枚举LookupError:错误{ 
案例teamMemberNotFound
案例编号OfMembersNotFound
}
枚举LookupResult {
成功案例(Int)
案例失败(LookupError)
}

在这里,我们创建了一个自定义的返回类型LookupResult ,其中包含两个枚举情况: success(Int)failure(LookupError) 。 成功案例将与Int关联,失败案例将与LookupError关联。 请注意, LookupError包含两个枚举情况, teamMemberNotFoundnumberOfMembersNotFound 。 这些情况恰好代表了我们先前方法中可能失败的两次检查! 现在,我们可以像这样重新编写我们的方法:

  func numberOfTeamMembers2(memberName:String)-> LookupResult { 
后卫让team = teamNames [memberName] else {
返回.failure(.teamMemberNotFound)
}
警卫让号= teamMembers [team] else {
返回.failure(.numberOfMembersNotFound)
}
返回.success(number)
}

同样,我们可以这样调用此方法:

let newLookup = numberOfTeamMembers2(memberName: "Dan")

现在,如果成功查找,则newLookup将包含一个Int ;如果newLookup则将包含一个LookupError 。 虽然我们必须花费更多的开销才能获得此结果,但它证明了在需要处理项目中的错误时自定义类型将是多么有益。 尽管,如果我们愿意的话,我们可以更进一步。

尽管前面的示例确实有助于解决我们的问题,但可以对其进行改进。 理想情况下,我们希望我们的LookupResult类型更通用,以便可以用于不同的任务。 基本上,我们不需要为我们在项目中解决的每种方法或问题创建新的结果类型。

要将泛型应用于前面的示例,我们可以创建一个新的结果类型和一个新的通用查找方法,如下所示:

 列举NewResult  { 
成功案例(T)
案例失败(SomeError)
}
func newLookup(memberName:String)-> NewResult {
后卫让team = teamNames [memberName] else {
返回.failure(.teamMemberNotFound)
}
警卫让号= teamMembers [team] else {
返回.failure(.numberOfMembersNotFound)
}
}

NewResult类型可用于在成功时返回任何通用类型T ,而在失败时返回任何SomeError (只要SomeError符合Error协议)。 这种通用返回类型的精度使我们能够利用Swift的类型检查优势,并可以在测试您的项目之前防止错误。 为了清楚起见,我们甚至可以switch上面编写的方法的结果。

 让teamMembersResult = newLookup(memberName:“ Samantha”)切换teamMembersResult { 
案例。成功(让号码):
// TODO:在此处处理成功流程
案例。失败(让错误):
// TODO:在此处处理错误流
}

使用上面的结果类型的目的并不是要完全替代我们项目中可选函数的实现。 毕竟,我们确实必须定义自定义枚举来解决相对简单的问题。 此外,偶尔对贡献者而言,相对于现有类型始终偏爱自定义类型的接口将不那么熟悉。

但是,使用NewResult类型是处理Swift中错误的好方法。 使用枚举案例有助于我们定义特定于问题的类型。