如何修复iOS Swift开发中Activity Indicator不显示/卡顿问题?
问题根因
IBAction默认在主线程触发,你调用的DispatchQueue.global().sync为同步调度,会阻塞当前主线程,直到全局队列内的全部任务执行完成才会释放主线程控制权- 全局队列中提交的
DispatchQueue.main.async启动指示器的UI任务,需要等待主线程空闲时才能执行,此时主线程被sync阻塞,直到抛硬币计算完成后,「启动指示器」和「停止指示器」两个UI任务会几乎同时执行,因此看不到加载动画
修复方案
核心修改
将DispatchQueue.global().sync替换为DispatchQueue.global().async,异步调度不会阻塞主线程,启动动画的UI任务可以及时执行。
可选优化
- 添加输入值合法性、上限校验,避免用户输入过大数值导致计算耗时过长
- 使用
[weak self]避免闭包循环引用风险 - 变量命名调整为Swift规范的小驼峰格式,避免和类型名混淆
- 确认
UIActivityIndicatorView的hidesWhenStopped属性设置为true,停止动画后自动隐藏
修复后参考代码
@IBOutlet weak var inputTextField: UITextField! @IBOutlet weak var headsLabel: UILabel! @IBOutlet weak var workingIndicator: UIActivityIndicatorView! @IBAction func toss(_ sender: Any) { // 收起键盘避免重复触发 inputTextField.resignFirstResponder() DispatchQueue.global().async { [weak self] in guard let self = self else { return } func integer(from textField: UITextField) -> Int { guard let text = textField.text, let number = Int(text), number > 0 else { return 0 } // 可根据需要调整上限值 return min(number, 1000000) } let input = integer(from: self.inputTextField) var runningTotal = 0 // 主线程启动加载动画 DispatchQueue.main.async { self.workingIndicator.startAnimating() } // 执行抛硬币计算 for _ in 0..<input { if Int.random(in: 0...1) == 1 { runningTotal += 1 } } // 主线程更新结果、停止动画 DispatchQueue.main.async { self.headsLabel.text = String(runningTotal) self.workingIndicator.stopAnimating() } } }
内容的提问来源于stack exchange,提问作者Aneesh Poddutur
相关产品推荐
相关产品推荐

