Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 快速-错误传播,同时保持api的清晰性_Ios_Swift_Error Handling - Fatal编程技术网

Ios 快速-错误传播,同时保持api的清晰性

Ios 快速-错误传播,同时保持api的清晰性,ios,swift,error-handling,Ios,Swift,Error Handling,通过在Swift中添加ErrorType,现在可以更清晰、更简洁地表达错误和故障事件。作为iOS开发者,我们不再拘泥于老式的NSError,笨重且难以使用 ErrorType之所以很棒,有几个原因: 函数中的泛型参数 任何枚举都可以符合并实现它 使用接球/掷球模式效果更好 然而,我最近遇到了一些问题,特别是一个问题,我很好奇其他人是如何解决这个问题的 比如说,你正在构建一个类似于Facebook的社交网络应用程序,你拥有Group模型。当用户首次加载应用程序时,您需要做两件/三件事: 从服务

通过在Swift中添加
ErrorType
,现在可以更清晰、更简洁地表达错误和故障事件。作为iOS开发者,我们不再拘泥于老式的
NSError
,笨重且难以使用

ErrorType
之所以很棒,有几个原因:

  • 函数中的泛型参数
  • 任何枚举都可以符合并实现它
  • 使用接球/掷球模式效果更好
然而,我最近遇到了一些问题,特别是一个问题,我很好奇其他人是如何解决这个问题的

比如说,你正在构建一个类似于Facebook的社交网络应用程序,你拥有
Group
模型。当用户首次加载应用程序时,您需要做两件/三件事:

  • 从服务器获取相关组
  • 获取磁盘上已持久化的组(领域、CoreData等)
  • 使用刚获取的远程副本更新本地副本
  • 在整个过程中,您可以将错误类型分为两个不同的类别:
    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> {
      ...
    }