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

iOS中DispatchQueue.main.async的正确用法:仅UI还是全逻辑?

关于iOS中DispatchQueue.main.async的正确使用与能耗分析

嘿,这个问题问得特别实用,刚好戳中了iOS开发里线程调度的关键细节!咱们一步步拆解:

一、核心原则:哪些代码必须放主队列?

只有UI相关操作(比如更新tableView、控制activityIndicator、修改UI控件属性等)和访问/修改UIKit框架类实例的代码,必须在主队列执行——因为UIKit是线程不安全的,非主队列操作UI会导致不可预料的崩溃或界面异常。

而像数据处理、数组增删、业务逻辑判断、打印日志这类非UI逻辑,完全可以留在后台线程执行,这样能避免占用主队列资源,让UI保持流畅。

二、两种实现的对比分析

1. 「仅UI操作放主队列」的实现(示例一)

这种做法是更规范、更高效的:

worldMessagesFunctions.delete(wmId: cell.worldMessageId) { response in 
    if let response = response { 
        if response.type == 1 { 
            // 非UI逻辑:后台线程处理数组删除
            if let index = WorldMessagesStore.shared.worldMessages.index(where: { $0.id! == cell.worldMessageId }) { 
                WorldMessagesStore.shared.worldMessages.remove(at: index) 
                // 仅UI操作丢去主队列执行
                DispatchQueue.main.async { 
                    self.tableView.beginUpdates() 
                    self.tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic) 
                    self.tableView.endUpdates() 
                } 
            } 
            print("Okay") 
        } 
    } else { 
        print("Error") 
    } 
    // UI操作丢去主队列
    DispatchQueue.main.async { 
        activityIndicator.stopAnimating() 
        activityIndicator.removeFromSuperview() 
    } 
}
  • 优点:把数组查找、删除这类计算型逻辑留在后台,主队列只处理必须的UI更新,减轻主线程负担,避免UI卡顿。
  • 注意点:如果WorldMessagesStore.shared.worldMessages是多线程共享的资源,要额外做线程安全处理(比如加锁、用线程安全的数组容器),防止数据竞争。

2. 「全部逻辑放主队列」的实现(示例二)

这种做法虽然不会导致UI崩溃,但效率很低:

worldMessagesFunctions.delete(wmId: cell.worldMessageId) { response in 
    DispatchQueue.main.async { 
        if let response = response { 
            if response.type == 1 { 
                if let index = WorldMessagesStore.shared.worldMessages.index(where: { $0.id! == cell.worldMessageId }) { 
                    WorldMessagesStore.shared.worldMessages.remove(at: index) 
                    self.tableView.beginUpdates() 
                    self.tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic) 
                    self.tableView.endUpdates() 
                } 
                print("Okay") 
            } 
        } else { 
            print("Error") 
        } 
        activityIndicator.stopAnimating() 
        activityIndicator.removeFromSuperview() 
    } 
}
  • 问题:主队列是串行队列,本来可以在后台并行处理的数组查找、业务判断,现在都挤到主队列里执行,会占用主线程的时间片,可能导致UI响应变慢(比如滑动tableView卡顿)。

三、能耗对比

第一种实现的能耗更低:

  • 后台线程可以利用CPU的多核资源并行处理非UI逻辑,主队列只处理轻量的UI更新,系统的线程调度更高效,不会让主队列长期处于繁忙状态。
  • 如果把所有逻辑都塞主队列,主队列忙的时候,其他后台线程可能处于闲置状态,CPU的多核资源没得到充分利用,反而会增加不必要的调度开销,导致能耗上升。

内容的提问来源于stack exchange,提问作者Kárpáti András

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:04:23