NSManagedObjectContext perform is only available in iOS 15 or newer

I'm working on an App that still supports iOS 13 and need to fetch some data with CoreData.

This is how I would normally do it

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

Now with Xcode 13.2 and async/await being available back to iOS 13 I get a compiler error

'perform(schedule:_:)' is only available in iOS 15.0 or newer

Jumping to definition shows the following new API in CoreData

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

When commenting out the code in the Block, it instead jumps to the old API in CoreData/NSManagedObjectContext

/* 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)

Why does the compiler select the new variant of perform and how can I force it to use the older non-async version?

I've added a sample project which replicates the issue https://github.com/iv-mexx/CoreDataRepro

The problem was, that I was doing everything, including the context.perform in one big do / catch block

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

The new extension method for perform is now marked as rethrows whereas the old one was not, so the fact there was a throwing method in the perform block meant the compiler selected the rethrowing perform which is only available on iOS >= 15.

@Cy-4AH on Stackoverflow suggested to use try? instead of try which works because the error is caught right there, not forcing the rethrowing method to be used.

Another solution is to move the do/catch inside the perform:

context.perform({
  do {
    let results = try context.fetch(request)
  } catch { 
    ...
  }
})
NSManagedObjectContext perform is only available in iOS 15 or newer
 
 
Q