活动指示器动画不起作用 - Swift

时间:2023-01-22 16:54:59

I have this problem when I load the screen I start an activity indicator and call a function to get the data. At first the activity was shown but never starts then I ran each call (start activity & get data) in a different thread. The animation worked but only once when I try to load the screen another time it's stuck again until the data is loaded. This is the viewDidLoad:

我加载屏幕时出现此问题我启动了一个活动指示器并调用一个函数来获取数据。首先显示活动但从未开始然后我在另一个线程中运行每个调用(启动活动和获取数据)。动画工作但只有一次当我尝试再次加载屏幕时它再次卡住,直到数据加载完毕。这是viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()

    //indicator
    indicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
    indicator.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
    indicator.color = commons.getButtonColor()
    indicator.center = self.view.center
    indicator.hidesWhenStopped = true
    self.view.addSubview(indicator)
    DispatchQueue.main.async {
        print("We finished that.")
        // only back on the main thread, may you access UI:
        self.indicator.startAnimating()
    }


    //connect to database
    commons.ref = Database.database().reference()

    //table view
    tableV.dataSource = self
    tableV.delegate = self
    tableV.tableFooterView = UIView()
    tableV.separatorStyle = .none
    tableV.allowsSelection = false

    //change left btn
    let leftButtonItem = UIBarButtonItem.init(
        title: "",
        style: .done,
        target: self,
        action: #selector(backButtonPressed)
    )
    leftButtonItem.image = UIImage(named:"back")
    leftButtonItem.tintColor = commons.getButtonColor()
    self.navigationItem.leftBarButtonItem = leftButtonItem

    //style
    self.title = flag

    DispatchQueue.main.async {
        //get values
        if(self.flag == "Accounts"){
            self.color = "d0f0dd"
            self.getAccounts()
        }else if(self.flag == "Loans"){
            self.color = "f8ff90"
           self.getLoans()
        }else if(self.flag == "Cards"){
            self.color = "ffa669"
            self.getCards()
        }
    }

}

A screenshot when the screenis stuck:

屏幕卡住时的屏幕截图:

活动指示器动画不起作用 -  Swift

Edit: The function to get data:

编辑:获取数据的功能:

func getAccounts(){
    commons.ref.child("Accounts").observeSingleEvent(of: .value, with: { (snapshot) in
        for item in snapshot.children {
            self.values.append(item as! DataSnapshot)
        }
        self.tableV.reloadData()
        self.indicator.stopAnimating()
    }) { (error) in
        print(error.localizedDescription)
    }
}

func getCards(){
    commons.ref.child("Cards").observeSingleEvent(of: .value, with: { (snapshot) in
        self.indicator.stopAnimating()
        for item in snapshot.children {
            self.values.append(item as! DataSnapshot)
        }
        self.tableV.reloadData()
    }) { (error) in
        print(error.localizedDescription)
    }
}

func getLoans(){
    commons.ref.child("Loans").observeSingleEvent(of: .value, with: { (snapshot) in
        self.indicator.stopAnimating()
        for item in snapshot.children {
            self.values.append(item as! DataSnapshot)
        }
        self.tableV.reloadData()
    }) { (error) in
        print(error.localizedDescription)
    }
}

1 个解决方案

#1


0  

There is a common error in all 3 of your functions. You are not calling stopAnimating on all possible branches of your code, so if the completion handler gets called with error, your activity indicator will keep running.

所有3个函数都有一个常见错误。您没有在代码的所有可能分支上调用stopAnimating,因此如果调用完成处理程序时出错,则您的活动指示符将继续运行。

I am not sure how Firebase's completion handlers are implemented, they might be dispatched to the main queue already, but to be absolutely safe, I'd also recommend dispatching the stopAnimating function call to the main thread to make sure you don't accidentally try to update the UI from a background thread.

我不知道火力地堡的完成处理程序是如何实现的,他们可能会被分派到主队列了,但要绝对安全,我也建议分派stopAnimating函数调用主线程,以确保你不小心尝试从后台线程更新UI。

func getAccounts(){
    commons.ref.child("Accounts").observeSingleEvent(of: .value, with: { (snapshot) in
        for item in snapshot.children {
            self.values.append(item as! DataSnapshot)
        }
        DispatchQueue.main.async{
            self.tableV.reloadData()
            self.indicator.stopAnimating()
        }
    }) { (error) in
        print(error.localizedDescription)
        DispatchQueue.main.async{
            self.indicator.stopAnimating()
        }
    }
}

You should make the same changes to your other two functions.

您应该对其他两个功能进行相同的更改。

#1


0  

There is a common error in all 3 of your functions. You are not calling stopAnimating on all possible branches of your code, so if the completion handler gets called with error, your activity indicator will keep running.

所有3个函数都有一个常见错误。您没有在代码的所有可能分支上调用stopAnimating,因此如果调用完成处理程序时出错,则您的活动指示符将继续运行。

I am not sure how Firebase's completion handlers are implemented, they might be dispatched to the main queue already, but to be absolutely safe, I'd also recommend dispatching the stopAnimating function call to the main thread to make sure you don't accidentally try to update the UI from a background thread.

我不知道火力地堡的完成处理程序是如何实现的,他们可能会被分派到主队列了,但要绝对安全,我也建议分派stopAnimating函数调用主线程,以确保你不小心尝试从后台线程更新UI。

func getAccounts(){
    commons.ref.child("Accounts").observeSingleEvent(of: .value, with: { (snapshot) in
        for item in snapshot.children {
            self.values.append(item as! DataSnapshot)
        }
        DispatchQueue.main.async{
            self.tableV.reloadData()
            self.indicator.stopAnimating()
        }
    }) { (error) in
        print(error.localizedDescription)
        DispatchQueue.main.async{
            self.indicator.stopAnimating()
        }
    }
}

You should make the same changes to your other two functions.

您应该对其他两个功能进行相同的更改。