代码之家  ›  专栏  ›  技术社区  ›  Martin

实现一个重发函数

  •  1
  • Martin  · 技术社区  · 7 年前

    我正在为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 回复  |  直到 7 年前
        1
  •  1
  •   Hamish    7 年前

    不完全理想,但有一种选择是只写两个重载“一个带一个不抛出的闭包,它本身不抛出,另一个带一个抛出闭包,它自己抛出。

    例如:

    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)
    }
    

    您应该能够使用两个重载,其方式与使用单个重新引发重载的方式大致相同。

    推荐文章