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

UITableView添加消息时延迟10秒后一次性显示问题求助

问题原因分析

你遇到的这个问题,核心原因是你在主线程里调用了usleep阻塞了UI刷新。

iOS的UI操作(包括tableView的插入行、滚动这些)都必须在主线程执行,而且主线程是串行处理任务的——它会按顺序处理队列里的UI更新、用户交互等任务。当你在循环里调用usleep(1000000)时,主线程被强制休眠,完全没法处理队列里的UI更新请求。所以虽然控制台每秒都在打印日志(因为打印操作不依赖UI线程的刷新),但所有的tableView插入操作都被积压在主线程的任务队列里,直到整个循环执行完、主线程恢复空闲后,才会一次性把所有UI更新任务执行完,这就导致10秒后所有行突然出现。


解决方案

你需要把延迟操作从主线程移开,用异步延迟的方式来逐个发送消息,让主线程能在每次消息插入后及时处理UI刷新。这里给你两种常用的实现方式:

方式一:用DispatchQueue.main.asyncAfter实现逐次延迟

修改你的循环逻辑,不要直接在主线程sleep,而是用异步延迟来安排下一条消息的发送:

let size = dictionary[key]!.count; 
let pointer = random(lower: 0, upper: UInt32(size) - 1); 
let part = dictionary[key]![pointer]; 

// 遍历消息数组,为每个消息设置对应的延迟时间
for (index, row) in part.enumerated() {
    if let message = row as? Message {
        // 第index条消息延迟index秒发送(第一条0秒,第二条1秒,以此类推)
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(index)) {
            self.sendMessage(message: message);
            print("MESSAGE TRIGGERED");
        }
    }
    if let question = row as? Question {
        // 这里处理Question逻辑
    }
}

这种方式的好处是不需要额外管理线程,直接利用GCD的异步延迟来调度任务,主线程可以在每次延迟期间正常处理UI刷新。

方式二:用Timer逐个发送消息(适合更复杂的序列控制)

如果需要更灵活的控制(比如中途可以暂停、取消),可以用Timer来逐个发送:

let size = dictionary[key]!.count; 
let pointer = random(lower: 0, upper: UInt32(size) - 1); 
let part = dictionary[key]![pointer]; 

// 把消息数组转成只包含Message的数组
let messages = part.compactMap { $0 as? Message }
var currentIndex = 0

// 创建定时器,每秒触发一次
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
    guard let self = self, currentIndex < messages.count else {
        timer.invalidate() // 所有消息发送完,销毁定时器
        return
    }
    let message = messages[currentIndex]
    self.sendMessage(message: message)
    print("MESSAGE TRIGGERED")
    currentIndex += 1
}
// 把定时器加入主运行循环(默认已经在,但显式写更稳妥)
RunLoop.current.add(timer, forMode: .common)

注意这里要用[weak self]避免循环引用,防止内存泄漏。


额外注意点
  • 你的sendMessage方法里的UI操作已经是在主线程执行的(因为你是从主线程调用它的),所以不需要再额外切换到主线程,但如果是在子线程调用的话,记得用DispatchQueue.main.async包裹UI操作。
  • 尽量避免在主线程里做任何阻塞操作(比如sleep、网络请求、大量计算),这些都会导致UI卡顿甚至无响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:12:04