求助:如何在从Firebase实时数据库接收数据时显示UIActivityIndicator?
解决Firebase实时数据库连接状态下UIActivityIndicator不显示的问题
我来帮你排查下这个UIActivityIndicator不生效的问题,你的代码里有几个关键问题导致它没正常工作,我给你梳理下并给出修正方案:
你的代码存在的问题
- 重复创建指示器实例:每次
.value事件触发时,你都会新建一个UIActivityIndicatorView,这会导致多个指示器被叠加添加到testView上,旧的实例无法被正确管理,显示逻辑混乱。 - 逻辑逻辑颠倒:连接成功时你调用了
stopAnimating()却设置isHidden = false,这会让停止动画的指示器一直停留在界面上;未连接时启动动画,但新创建的指示器可能还没完成布局或属性配置,导致看不到效果。 - 样式适配问题:如果
testView或父视图的背景色是白色,whiteLarge样式的指示器会因为颜色相近而无法被看到。
修正后的完整代码
首先,把指示器作为ViewController的类属性,确保只初始化一次:
import UIKit import FirebaseDatabase class YourViewController: UIViewController { // 声明指示器为类属性 var myActivityIndicator: UIActivityIndicatorView! // 假设你的testView是已存在的视图 @IBOutlet weak var testView: UIView! override func viewDidLoad() { super.viewDidLoad() // 初始化并配置指示器 setupActivityIndicator() // 监听Firebase连接状态 monitorFirebaseConnection() } private func setupActivityIndicator() { // 选择合适的样式,这里用grayLarge适配更多背景色 myActivityIndicator = UIActivityIndicatorView(style: .grayLarge) myActivityIndicator.translatesAutoresizingMaskIntoConstraints = false // 可以自定义颜色 myActivityIndicator.color = .systemBlue // 默认隐藏,未连接时再显示 myActivityIndicator.isHidden = true // 添加到testView(如果需要全屏显示就添加到self.view) testView.addSubview(myActivityIndicator) // 设置约束确保在容器中心 NSLayoutConstraint.activate([ myActivityIndicator.centerXAnchor.constraint(equalTo: testView.centerXAnchor), myActivityIndicator.centerYAnchor.constraint(equalTo: testView.centerYAnchor) ]) } private func monitorFirebaseConnection() { let connectedRef = Database.database().reference(withPath: ".info/connected") // 使用[weak self]避免循环引用 connectedRef.observe(.value, with: { [weak self] snapshot in guard let self = self else { return } let isConnected = snapshot.value as? Bool ?? false if isConnected { print("Connected to Firebase") // 连接成功:停止动画并隐藏 self.myActivityIndicator.stopAnimating() self.myActivityIndicator.isHidden = true } else { print("Not connected to Firebase") // 未连接:显示并启动动画 self.myActivityIndicator.isHidden = false self.myActivityIndicator.startAnimating() } }) } }
额外注意点
.info/connected仅监听网络与Firebase的连接状态,如果需要在加载具体数据时显示指示器(比如拉取某个节点的数据),还要在数据请求的开始和结束分别控制指示器:
// 示例:加载某个数据节点时显示指示器 func loadDataFromFirebase() { // 开始加载:显示指示器 myActivityIndicator.isHidden = false myActivityIndicator.startAnimating() Database.database().reference().child("yourDataNode").observeSingleEvent(of: .value) { [weak self] snapshot in guard let self = self else { return } // 处理数据逻辑 print("Data loaded: \(snapshot.value)") // 加载完成:隐藏指示器 self.myActivityIndicator.stopAnimating() self.myActivityIndicator.isHidden = true } withCancel: { [weak self] error in guard let self = self else { return } // 加载失败:也需要隐藏指示器 print("Load data error: \(error.localizedDescription)") self.myActivityIndicator.stopAnimating() self.myActivityIndicator.isHidden = true } }
内容的提问来源于stack exchange,提问作者Gurjit Singh
相关产品推荐
相关产品推荐

