0

我正在开发一个仍然支持 iOS 13 并且需要使用 CoreData 获取一些数据的应用程序。

这就是我通常会这样做的方式

context.perform({
  let results = try context.fetch(request)
})

现在,随着 Xcode 13 和 async/await 可用于 iOS 13,我得到一个编译器错误

'perform(schedule:_:)' 仅适用于 iOS 15.0 或更高版本

跳转到定义显示 CoreData 中的以下新 API

@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
extension NSManagedObjectContext {

    public func performAndWait<T>(_ block: () throws -> T) rethrows -> T

    public func perform<T>(schedule: NSManagedObjectContext.ScheduledTaskType = .immediate, _ block: @escaping () throws -> T) async rethrows -> T
}

当注释掉 Block 中的代码时,它会跳转到 CoreData/NSManagedObjectContext 中的旧 API

/* asynchronously performs the block on the context's queue.  Encapsulates an autorelease pool and a call to processPendingChanges */
@available(iOS 5.0, *)
open func perform(_ block: @escaping () -> Void)

为什么编译器会选择新的变体,perform如何强制它使用旧的非异步版本?

编辑:这是一个演示该问题的最小示例项目:https ://github.com/iv-mexx/CoreDataRepro

4

1 回答 1

0

感谢@Cy-4AH,我想通了!

问题是,我正在做所有事情,包括context.perform在一个大街do / catch

do {
    ...
    context.perform({
      let results = try context.fetch(request)
    })
    ...
} catch { 
    ...
}

新的扩展方法perform现在被标记为,rethrows而旧的没有,所以在执行块中有一个抛出方法意味着编译器选择了perform仅在 iOS >= 15 上可用的重新抛出方法。

@Cy-4AH 建议使用whichtry?代替trywhich 有效,因为错误就在那里被捕获,而不是强制使用该rethrowing方法。

另一种解决方案是移动do/catch内部perform

context.perform({
  do {
    let results = try context.fetch(request)
  } catch { 
    ...
  }
})
于 2022-01-20T09:04:21.333 回答