【问题标题】:Swift - Value not updating after completion handlerSwift - 完成处理程序后不更新值
【发布时间】:2018-09-14 22:05:09
【问题描述】:

我是 Swift 编程新手,并试图为我的 tableView numberOfSections 返回一个值。我也是完成处理程序的新手。如果我进入调试模式并逐行运行我的代码,count 确实会在 numberOfSections 中“更新”。然而,当它到达 return 语句时,count 仍然是 0。

override func numberOfSections(in tableView: UITableView) -> Int {

    var count = 0
    let firebase = ref.child("Menu").child("Category").child("Cookies")
    getCount(ref: firebase) { (myCount) in
        print("Complete")
        count = myCount
    }
    return count
}

func getCount(ref:DatabaseReference, completion: @escaping (Int) -> ()){
    var count = 0
    ref.observeSingleEvent(of: .value) { (snapshot) in
        count = Int(snapshot.childrenCount)
        completion(count)
    }
}

【问题讨论】:

  • return count 不是 after 完成处理程序。您的 getCount(ref:completion:) 在您的完成处理程序执行之前立即返回。所以,return count 被执行,而count 仍然是0。在异步操作完成一段时间后,将执行您的完成处理程序{ (myCount) in ... }。通常,您不能在 numberOfSections(in:) 中使用异步方法。将您的数据模型加载到其他地方并在加载完成时调用tableView.reloadData()。 Sh_Khan 的回答很好地概述了您需要做的事情。
  • 你不会想要这样做——它会变得迟钝并且不会为用户提供良好的体验。最佳做法是将要在 tableview 中显示的数据加载到数据源中,然后填充 tableview。计数将来自该数据源,因此它将减少 ping Firebase。 TableViews、collectionViews 等应该由内存中的datasource 支持。然后查看Pagination

标签: swift uitableview firebase


【解决方案1】:

这个过程是异步的,你需要

var count = 0 // instance var

override func viewDidLoad() {
    super.viewDidLoad() // you missed this =D
    let firebase = ref.child("Menu").child("Category").child("Cookies")
    getCount(ref: firebase) { (myCount) in
        print("Complete")
        count = myCount
        self.tableView.reloadData()
    }
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return count
}

【讨论】:

    【解决方案2】:

    count 变量没有在 numberOfSections 函数中更新的原因有几个。

    1. Count 是一个 Int,这使它成为一种值类型,这意味着在闭包中进行了复制,因此闭包内的计数与闭包外的计数不同。
    2. 从数据库中获取是异步的,这意味着在执行闭包之前将返回计数并超出范围。

    试试这个看看是否有效。

        // this variable now lives beyond the scope of the function
        var sectionCount: Int = 0 
    
        // fetch every time you come into this screen, 
        // so pushing and popping new screens on top of this one
        // will update it
        override func viewWillAppear() {
            super.viewWillAppear()
    
            // make your async call to your db
            let firebase = ref.child("Menu").child("Category").child("Cookies")
    
            // remember to weak reference 'self' to avoid retain cycles
            getCount(ref: firebase) { [weak self] (myCount) in
                // update the section count
                self?.sectionCount = myCount
                // tell the table view to update itself, this will tell it 
                // to call numberOfSections, cellForIndex, and other functions 
                // to update the table view 
                self?.tableView.reloadData()
            }
        }
    
        override func numberOfSections(in tableView: UITableView) -> Int {
            return self.sectionCount
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      相关资源
      最近更新 更多