【问题标题】:Activity indicator animation not working - Swift活动指示器动画不起作用 - Swift
【发布时间】:2018-05-05 10:19:47
【问题描述】:

我在加载屏幕时遇到了这个问题,我启动了一个活动指示器并调用了一个函数来获取数据。起初显示活动但从未开始,然后我在不同的线程中运行每个调用(开始活动和获取数据)。动画有效,但只有一次,当我尝试再次加载屏幕时,它再次卡住,直到加载数据。 这是 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()
        }
    }

}

卡屏时的截图:

编辑:获取数据的函数:

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)
    }
}

【问题讨论】:

  • 你从来没有打电话给self.indicator.stopAnimating(),那为什么活动指示器会消失呢?
  • 哦,是的,我在调用它,在我获取数据的函数中,这不是出现/消失的问题,指示器根本没有 stsrt 动画,页面卡住直到加载数据那么一切都很好。
  • 这表明你在某处阻塞了主线程。请包括所有相关功能,因为在您问题的代码中似乎没有任何问题可能导致您的问题。
  • 我猜你可能从主线程中的 Web 服务获取数据。在数据到达之前,用户界面将被冻结。使用获取数据的代码更新您的问题。确保将服务分派到非主线程。 @yasserh
  • 问题已更新。

标签: ios iphone swift animation activity-indicator


【解决方案1】:

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

我不确定 Firebase 的完成处理程序是如何实现的,它们可能已经分派到主队列,但为了绝对安全,我还建议将 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()
        }
    }
}

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

【讨论】:

  • 感谢您的回复,但问题仍然存在,指示器一开始工作,但如果我再次访问该页面,用户界面被冻结。
  • @yasserh 你的意思是如果你从有问题的视图控制器移动到另一个,然后返回,数据没有更新? viewDidLoad 只被调用一次,当类实例加载到内存中时,所以如果你想在视图控制器之间来回导航时重新加载数据,你应该调用从 viewWillAppear 更新你的 UI 的函数。
  • 当然不是,流程如下:ServicesList -> accounts (indicator working) 现在回到 servicesList -> accounts (ui freeze) 所以 viewDidLoad 肯定会被调用。
  • 问题:UI 会受到以前的屏幕的影响吗?不同屏幕中的其他动画也无法正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多