为何UIActivityIndicatorView仅首次显示时动效正常,后续无动画?
问题分析与解决方案
问题原因
首次断网时动画正常,第二次断网时指示器无动画,核心原因是视图被反复从导航栏移除和添加:
- 联网时将
navigationItem.titleView设为nil,导致包含指示器的containerView被从视图层级中移除; - 配合
activityIndicator.hidesWhenStopped = true的设置,调用stopAnimating()后指示器会被隐藏; - 第二次断网重新添加
containerView时,虽然调用了startAnimating(),但由于视图刚被重新加入层级,动画状态未能正确触发。
解决方案
方案一:通过控制视图隐藏状态切换(推荐)
避免反复移除/添加containerView,始终将其作为titleView,仅通过isHidden控制显示/隐藏,状态更稳定:
- 在
viewDidLoad中提前设置titleView并初始隐藏:
override func viewDidLoad() { label.text = "Waiting for network" label.font = UIFont.systemFont(ofSize: 17) label.textColor = .black containerView.addSubview(self.activityIndicator) containerView.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false self.activityIndicator.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ self.activityIndicator.centerYAnchor.constraint(equalTo: containerView.centerYAnchor), self.activityIndicator.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), label.centerYAnchor.constraint(equalTo: containerView.centerYAnchor), label.leadingAnchor.constraint(equalTo: self.activityIndicator.trailingAnchor, constant: 8), containerView.widthAnchor.constraint(equalTo: label.widthAnchor, constant: self.activityIndicator.frame.width + 8) ]) // 提前设置titleView并初始隐藏 self.navigationItem.titleView = self.containerView self.containerView.isHidden = true super.viewDidLoad() }
- 修改
onUpdate方法:
func onUpdate(_ isConnected: Bool) { print("isInternetConnected changed to: \(isConnected)") DispatchQueue.main.async { if isConnected { self.containerView.isHidden = true self.navigationItem.title = "Chats" self.activityIndicator.stopAnimating() } else { self.containerView.isHidden = false self.navigationItem.title = nil self.activityIndicator.startAnimating() } } }
方案二:强制触发视图布局后启动动画
如果必须切换titleView,则在启动动画前强制完成视图布局,确保指示器处于有效视图层级中:
func onUpdate(_ isConnected: Bool) { print("isInternetConnected changed to: \(isConnected)") DispatchQueue.main.async { if isConnected { self.navigationItem.titleView = nil self.activityIndicator.stopAnimating() self.navigationItem.title = "Chats" } else { self.navigationItem.titleView = self.containerView // 强制完成布局,确保视图已加入层级 self.containerView.layoutIfNeeded() // 手动取消隐藏并启动动画 self.activityIndicator.isHidden = false self.activityIndicator.startAnimating() } } }
总结
方案一避免了视图的频繁创建和销毁,符合iOS视图管理的最佳实践,状态稳定性更高,推荐优先使用。
内容的提问来源于stack exchange,提问作者Edward Tattsyrup
相关产品推荐
相关产品推荐

