Ios 快速-错误传播,同时保持api的清晰性
通过在Swift中添加Ios 快速-错误传播,同时保持api的清晰性,ios,swift,error-handling,Ios,Swift,Error Handling,通过在Swift中添加ErrorType,现在可以更清晰、更简洁地表达错误和故障事件。作为iOS开发者,我们不再拘泥于老式的NSError,笨重且难以使用 ErrorType之所以很棒,有几个原因: 函数中的泛型参数 任何枚举都可以符合并实现它 使用接球/掷球模式效果更好 然而,我最近遇到了一些问题,特别是一个问题,我很好奇其他人是如何解决这个问题的 比如说,你正在构建一个类似于Facebook的社交网络应用程序,你拥有Group模型。当用户首次加载应用程序时,您需要做两件/三件事: 从服务
ErrorType
,现在可以更清晰、更简洁地表达错误和故障事件。作为iOS开发者,我们不再拘泥于老式的NSError
,笨重且难以使用
ErrorType
之所以很棒,有几个原因:
- 函数中的泛型参数
- 任何枚举都可以符合并实现它
- 使用接球/掷球模式效果更好
Group
模型。当用户首次加载应用程序时,您需要做两件/三件事:
PersistenceError
和NetworkError
,其中ErrorType
符合条件的枚举可能如下所示
enum PersistenceError: ErrorType {
case CreateFailed([String: AnyObject)
case FetchFailed(NSPredicate?)
}
enum NetworkError: ErrorType {
case GetFailed(AnyObject.Type) // where AnyObject is your Group model class
}
有几种方法/设计模式可用于传递错误。最常见的当然是尝试/抓住
func someFunc() throws {
throw .GetFailed(Group.self)
}
在这里,由于抛出的函数还不能指定它们抛出的错误类型,尽管我怀疑这会改变,您可以轻松抛出NetworkError
或PersistenceError
当使用更通用的或功能性的方法时,如ReactiveCocoa或Result,麻烦就来了
func fetchGroupsFromRemote() -> SignalProducer<[Group], NetworkError> {
// fetching code here
}
func fetchGroupsFromLocal() -> SignalProducer<[Group], PersistenceError> {
// fetch from local
}
它本质上是一个长错误枚举,因此任何和所有错误都属于同一类型,甚至最深的错误都可以向上传播
其他人是如何处理的?我享受拥有一个通用错误枚举的好处,但可读性和api澄清会受到影响。我更愿意让每个函数描述它们返回的特定错误簇,而不是让每个函数都返回
错误,但我不知道如何在不丢失错误信息的情况下执行此操作。仅尝试解决您的问题,可能不是一个完美的解决方案。使用协议轻松传递错误对象:
//1.
protocol Error {
func errorDescription()
}
//2.
enum PersistenceError: ErrorType, Error {
case CreateFailed([String: AnyObject)
case FetchFailed(NSPredicate?)
func errorDescription() {
}
}
//3.
enum NetworkError: ErrorType, Error {
case GetFailed(AnyObject.Type) // where AnyObject is your Group model class
func errorDescription() {
}
}
//5.
func fetch() -> SignalProducer<Group, Error> {
...
}
//1。
协议错误{
func errorDescription()
}
//2.
枚举持久性错误:错误类型,错误{
case CreateFailed([字符串:AnyObject)
案例获取失败(NSPredicate?)
func errorDescription(){
}
}
//3.
枚举网络错误:错误类型,错误{
case GetFailed(AnyObject.Type)//其中AnyObject是您的组模型类
func errorDescription(){
}
}
//5.
func fetch()->SignalProducer{
...
}
这当然是一个很好的解决方案。不幸的是,它仍然存在同样的问题,即任何返回错误类型的函数或方法都将始终是error
类型。对,但即使类型是error,它实际上是一个带有基类指针的子类对象。并且您可以根据子类获得动态行为协议方法的类型实现。可能我没有准确地获取上下文,但您也可以通过向ErrorType添加扩展方法来改进行为,并将其无缝地用于任何自定义子类类型。
enum Error: ErrorType {
// Network Errors
case .GetFailed
// Persistence Errors
case .FetchFailed
// More error types
}
//1.
protocol Error {
func errorDescription()
}
//2.
enum PersistenceError: ErrorType, Error {
case CreateFailed([String: AnyObject)
case FetchFailed(NSPredicate?)
func errorDescription() {
}
}
//3.
enum NetworkError: ErrorType, Error {
case GetFailed(AnyObject.Type) // where AnyObject is your Group model class
func errorDescription() {
}
}
//5.
func fetch() -> SignalProducer<Group, Error> {
...
}