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

Swift中如何在执行耗时任务前优先完成界面UI更新?

问题原因

所有UIKit的UI变更操作都不会立刻触发屏幕渲染,而是会等到当前主队列RunLoop的渲染周期到来时才会批量提交绘制。你的代码全部运行在主队列中:

  • 第一行button.setTitleColor(.clear, for: .normal)执行后,仅在内存中标记了按钮样式需要更新,没有立刻渲染到屏幕
  • 第二行的Basket.addItems是耗时操作,直接在主队列执行时会阻塞主队列RunLoop,导致之前的UI更新渲染任务被挂起,直到耗时任务执行完成后,RunLoop才会处理UI更新请求,因此你会看到UI要等耗时任务结束才变更。
解决方案

核心逻辑是UI更新保留在主队列执行,耗时任务放到后台队列执行,避免阻塞主队列的渲染流程,参考实现代码如下:

@objc private func addItemsToBasket(_ button: UIButton) {
    // 主队列更新UI,会在当前RunLoop周期结束后立刻渲染到屏幕
    button.setTitleColor(.clear, for: .normal)
    
    // 耗时任务抛到全局后台队列执行,不阻塞主队列
    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        guard let self = self else { return }
        Basket.addItems(keys: self.planner.currentDayKeys())
        
        // 若耗时任务结束后需要更新UI,必须切回主队列执行
        DispatchQueue.main.async {
            // 此处放置后续UI操作,例如更新购物车角标、提示添加成功等
        }
    }
}

注意事项

  • 所有UI相关操作必须放在主队列执行,不要在后台队列操作UI,否则会出现偶现崩溃、UI更新异常等问题
  • 如果之前尝试GCD未生效,大概率是两种原因:一是误将UI更新代码放到了后台队列,二是耗时任务仍然留在主队列执行,没有真的放到后台队列

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:54:03