iOS 13兼容项目中CoreData NSManagedObjectContext perform方法编译器选择iOS15+API的原因及强制使用旧版本方法的方案
iOS 13兼容下CoreData
perform方法的编译错误问题解析 为什么编译器会优先选择iOS 15+的新版perform?
这事儿得从Swift的重载匹配逻辑说起:
- 你写的闭包里用到了
try context.fetch(request),这个闭包的类型是() throws -> [YourEntityType](带有抛出特性且有返回值)。 - 旧版的
perform(_ block: @escaping () -> Void)只接受无返回、不可抛出的闭包,完全不匹配你的闭包类型。 - 而iOS15新增的
perform<T>(schedule:_:)恰好接受() throws -> T类型的闭包,所以编译器会优先选中这个重载——哪怕你没写await,也没指定返回值接收,它还是会匹配这个类型最贴合的方法,于是就出现了“仅iOS15+可用”的编译错误。
当你注释掉闭包里的代码后,闭包变成了() -> Void,这时候旧版方法就成了唯一匹配的选项,编译器自然就跳转到旧版API了。
如何强制使用iOS 13兼容的旧版perform方法?
给你几个靠谱的解决思路:
1. 把闭包改成无抛出的() -> Void类型
在闭包里处理fetch的错误,让闭包不再带有抛出特性:
context.perform { do { let results = try context.fetch(request) // 处理获取到的结果 } catch { // 这里处理fetch失败的错误 } }
这时候闭包的类型就是() -> Void,编译器会自动匹配旧版的perform方法,完美兼容iOS13。
2. 显式标注闭包类型
直接给闭包加上类型标注,告诉编译器你要使用旧版方法:
context.perform({ () -> Void in do { let results = try context.fetch(request) // 处理结果 } catch { // 处理错误 } })
3. 改用performAndWait(同步执行场景)
如果你的场景不需要异步执行,iOS5+就存在的performAndWait是更好的选择——它支持抛出错误,同时完全兼容iOS13:
do { let results = try context.performAndWait { try context.fetch(request) } // 处理结果 } catch { // 处理错误 }
这个方法会在当前线程阻塞,直到闭包执行完成,适合不需要异步的场景。
内容的提问来源于stack exchange,提问作者MeXx
相关产品推荐
相关产品推荐

