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

求助:如何在从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:09:55