NSManagedObjectContext Async/Await выполнить (расписание:_:)» доступно только в iOS 15.0 или новее.
Я работаю над приложением, которое по-прежнему поддерживает iOS 13, и мне нужно получить некоторые данные с помощью CoreData.
Вот как я обычно это делаю
context.perform({
let results = try context.fetch(request)
})
Теперь, когда Xcode 13 и async/await доступны обратно в iOS 13, я получаю ошибку компилятора.
'выполнить (расписание:_:)' доступно только в iOS 15.0 или новее
Переход к определению показывает следующий новый API в 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
}
При комментировании кода в блоке он вместо этого переходит к старому API в 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)
Почему компилятор выбирает новый вариант
perform
и как я могу заставить его использовать более старую неасинхронную версию?
Изменить: Вот минимальный пример проекта, демонстрирующий проблему: https://github.com/iv-mexx/CoreDataRepro .
1 ответ
Благодаря @Cy-4AH я понял это!
Проблема была в том, что я делал все, включая
context.perform
в одном большом
do / catch
блокировать
do {
...
context.perform({
let results = try context.fetch(request)
})
...
} catch {
...
}
Новый метод расширения для теперь помечен как
rethrows
тогда как старый не был, поэтому тот факт, что в блоке выполнения был метод броска, означал, что компилятор выбрал повторный бросок, который доступен только на iOS>= 15.
@Cy-4AH предложил использовать
try?
вместо
try
который работает, потому что ошибка ловится прямо там, не заставляя
rethrowing
метод, который будет использоваться.
Другим решением является перемещение
do/catch
внутри
perform
:
context.perform({
do {
let results = try context.fetch(request)
} catch {
...
}
})