You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何同步工作任务与进度视图控制器的展示、销毁流程

解决方案

方案1:CheckedContinuation封装异步present(兼容性最优,iOS 15+支持)

通过withCheckedContinuation将UIKit的回调式API转为async/await风格,再用async let同时执行弹窗弹出和查询任务,自动等待两个任务全部完成后再执行后续逻辑,不需要硬编码超时时间,符合Swift Concurrency设计规范。
首先扩展UIViewController:

extension UIViewController {
    @MainActor
    func present(_ viewController: UIViewController, animated: Bool) async {
        await withCheckedContinuation { continuation in
            present(viewController, animated: animated) {
                continuation.resume()
            }
        }
    }
}

使用示例:

let progressController = UIAlertController(title: "Progress", message: nil, preferredStyle: .alert)
// 同时启动两个异步任务,互不阻塞
async let presentFinish: () = self.present(progressController, animated: true)
async let queryFinish: () = yourQueryTask() // 替换为你的实际耗时查询异步方法

// 等待两个任务全部完成
_ = await [presentFinish, queryFinish]

// 执行后续逻辑
progressController.dismiss(animated: true) {
    // 弹出结果视图控制器
}

方案2:AsyncSemaphore(iOS 16+,适配二元信号量使用习惯)

如果你更熟悉信号量的同步逻辑,可以使用Swift Concurrency原生的AsyncSemaphore实现二元信号量效果,不会阻塞线程,写法和GCD信号量高度一致:

// 初始化信号量为0
let presentSemaphore = AsyncSemaphore(value: 0)
let controller = UIAlertController(title: "Progress", message: nil, preferredStyle: .alert)
// present完成时发送信号
self.present(controller, animated: true, completion: { presentSemaphore.signal() })

Task { @MainActor in
    // 执行耗时查询任务
    try await Task.sleep(nanoseconds: 10_000_000)
    
    // 等待present完成的信号
    await presentSemaphore.wait()
    
    // 执行后续逻辑
    controller.dismiss(animated: true)
    // 弹出结果视图控制器
}
注意事项
  • 所有UI相关操作需要在主Actor执行,示例中已经添加@MainActor修饰避免线程异常。
  • 两种方案都不需要硬编码超时时间,完全依赖系统回调触发同步,稳定性远高于原有的固定时长sleep方案。

内容的提问来源于stack exchange,提问作者Jimmie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 13:24:07