实施重投功能

时间:2018-07-18 12:53:58

标签: swift error-handling try-catch throw

我正在为CoreData实现一个辅助方法

public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
    guard let context = mainQueueContext else { return }
    context.performAndWait({
        block(context)
    })
}

它运作良好,可以这样称呼:

CoreDataManager().doInMain { moc in
    // do your fetch request with managed object context
}

但是当我想尝试doInMain块中的错误时,这很烦人,因为调用函数无法将其抛出。由于集团是nonescaping,因此应该这样做。

所以我添加了:

public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) rethrows {
    guard let context = mainQueueContext else { return }
    context.performAndWait({
        try block(context)
    })
}

但是NSManagedObjectContext.performAndWait不会抛出错误,因此不会编译。

它尝试过:

public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) rethrows {
    guard let context = mainQueueContext else { return }
    var thrownError: Error?
    context.performAndWait({
        do { try block(context) }
        catch { thrownError = error }
    })
    if let error = thrownError {
        throw error
    }
}

但是现在编译器说A function declared 'rethrows' may only throw if its parameter does

我搞砸了吗?有解决方法吗?

谢谢

1 个答案:

答案 0 :(得分:1)

并非完全理想,但一种选择是只编写两个重载-一个重载不引发并且本身不引发的闭包,另一个重载引发不引发自身的闭包。

例如:

public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
  guard let context = mainQueueContext else { return }
  context.performAndWait {
    block(context)
  }
}

public func doInMain(_ block: (NSManagedObjectContext) throws -> Void) throws {
  guard let context = mainQueueContext else { return }
  var thrownError: Error?
  context.performAndWait {
    do {
      try block(context)
    } catch {
      thrownError = error
    }
  }
  if let error = thrownError {
    throw error
  }
}

请记住,如果需要,您总是可以根据抛出超载实现非抛出超载:

public func doInMain(_ block: (NSManagedObjectContext) -> Void) {
  let fn = doInMain as ((NSManagedObjectContext) throws -> Void) throws -> Void
  try! fn(block)
}

您应该能够以与单个重新抛出过载大致相同的方式使用这两个过载。