DispatchQueue.main.asyncAfter使用可变条件时的执行行为疑问
解答
1. 动态变量的取值逻辑
你代码里的延迟闭包捕获的是viewModel的引用,不是调用asyncAfter那一刻someBool的瞬时值,所以3.5秒后闭包触发时,读到的是someBool最新的值,也就是你后续修改后的false,这一点是确定的。
2. 主线程延迟闭包的调度规则
DispatchQueue.main是串行队列,所有提交到主线程的任务严格按顺序执行,同一时间只会跑一个任务:
asyncAfter的deadline是「最早可执行时间」,不是精确的执行时间,3.5秒计时到了之后,这个闭包才会被加到主线程的任务队列末尾,必须等队列里排在它前面的所有已提交任务全部执行完,才会轮到它跑,不会提前插队。- 绝对不会出现闭包插入其他主线程代码块执行过程中运行的情况。主线程的调度机制保证了每个主线程任务都是原子执行的,一个任务要么没开始,要么完整执行完才会调度下一个,不存在执行到一半被其他主线程任务打断的可能。
3. 潜在风险说明
你当前的写法本身没有线程安全问题:所有对someBool的读写、延迟闭包的执行都在主线程,不会出现数据竞争的Bug。
唯一可以优化的点是:如果你的业务场景允许3.5秒内viewModel被释放,建议在闭包的捕获列表加[weak viewModel],避免闭包强持有viewModel导致不必要的内存泄漏,优化后代码如下:
DispatchQueue.main.asyncAfter(deadline: .now() + 3.5) { [weak viewModel] in guard let viewModel = viewModel, viewModel.someBool else { return } // 执行目标逻辑 }
内容的提问来源于stack exchange,提问作者E. M
相关产品推荐
相关产品推荐

