为何UIViewController的present、dismiss无Swift异步导入版本?
为什么UIViewController的present/dismiss方法没有被Swift自动导入为异步版本?
苹果《异步调用Objective-C API》文档指出,满足特定条件的Objective-C方法会被Swift以两种形式导入,其中一种是带
async关键字的无完成回调版本——当方法有多个参数,且最后一个参数的选择器片段为completion时,Swift会自动生成异步版本。
按照这个规则,UIViewController的present(_:animated:completion:)对应的Objective-C签名为presentViewController:animated:completion:,理论上应该生成如下异步版本:
func present(_ viewControllerToPresent: UIViewController, animated flag: Bool) async
dismiss方法同理,但实际在Xcode中并没有这些内置的异步版本,且原方法仍是Objective-C源码实现。
原因分析
你对官方文档的基础规则理解没有错误,但存在文档未明确提及的UIKit核心API例外情况:
present和dismiss的异步行为与视图控制器的生命周期、UIKit内部的UI调度逻辑深度绑定,自动生成async版本可能引发意料之外的问题(比如异步调用悬停时视图控制器的释放时机冲突)。- 苹果对UIKit API的异步适配采用手动控制节奏的策略,目前尚未将这两个方法纳入自动转换的范围。
手动封装异步版本
如果需要使用async/await形式的present和dismiss,可以自行扩展封装:
extension UIViewController { func present(_ viewControllerToPresent: UIViewController, animated flag: Bool) async { await withCheckedContinuation { continuation in present(viewControllerToPresent, animated: flag) { continuation.resume() } } } func dismiss(animated flag: Bool) async { await withCheckedContinuation { continuation in dismiss(animated: flag) { continuation.resume() } } } }
内容的提问来源于stack exchange,提问作者shim
相关产品推荐
相关产品推荐

