【问题标题】:What am I doing wrong while populating this UITableView in Swift?在 Swift 中填充这个 UITableView 时我做错了什么?
【发布时间】:2020-09-27 19:37:06
【问题描述】:

我正在尝试使用数组填充 UITableView,但我无法这样做。这是我到目前为止所拥有的。此代码用于检索数据并将其存储在我用来填充 UITableView 的数组中:

func prepareForRetrieval() {
        Database.database().reference().child("UserCart").child(Auth.auth().currentUser!.uid).observe(.value, with: {
            (snapshot) in
            for snap in snapshot.children.allObjects {
                let id = snap as! DataSnapshot
                self.keyArray.append(id.key)
            }
            self.updateCart()
        })
    }
func updateCart() {
        for key in keyArray {
            Database.database().reference().child("UserCart").child(Auth.auth().currentUser!.uid).child(key).observeSingleEvent(of: .value, with: {
                (snapshot) in
                let value = snapshot.value as? NSDictionary
                let itemName = value?["Item Name"] as! String
                let itemPrice = value?["Item Price"] as! Float
                let itemQuantity = value?["Item Quantity"] as! Int
                self.cartArray.append(CartData(itemName: itemName, itemQuantity: itemQuantity, itemPriceNumber: itemPrice))
                print(self.cartArray.count)
            })
        }
    }

数据正确地附加到数组中,当我打印数组的计数时,它会打印正确的计数。这意味着数据在那里。但是,当我尝试填充 UITableView 时,它没有检测到任何数据。在尝试填充 UITableView 之前,我有以下代码来确保数组中有数据:

override func viewDidLoad() {
        super.viewDidLoad()

        cartBrain.prepareForRetrieval()

        if cartBrain.cartArray.isEmpty == false{
            tableViewOutlet.dataSource = self
            tableViewOutlet.reloadData()
        }
        else {
            tableViewOutlet.isHidden = true
            tableViewOutlet.isUserInteractionEnabled = false
            purchaseButtonOutlet.isEnabled = false
            cartEmptyLabel.text = "Your cart is empty. Please add items and check back later."
        }
}

当我打开 View Controller 时,TableView 被禁用,因为它没有检测到任何数据。我已经将数据源设置为 self ,问题是当打印数组的计数时,它会再次打印正确的数量。我已经将 UITableView 的数据源设置为 self。这是我的 UITableView 代码:

extension CartViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cartBrain.cartArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cartcustomcell", for: indexPath)
        cell.textLabel?.text = cartBrain.cartArray[indexPath.row].itemName
        cell.detailTextLabel?.text = String(cartBrain.cartArray[indexPath.row].itemQuantity)
        return cell
    }
}

我不明白为什么数组的计数打印出正确的数量,这意味着其中存储了数据,但是当加载视图控制器时,它检测到数组为空。感谢您的帮助,如果问题有点不清楚,我很抱歉。

【问题讨论】:

  • 请注意 prepareForRetrieval 是异步的,是吗?所以整个viewDidLoad 运行first,然后then self.updateCart 被调用。见programmingios.net/what-asynchronous-means等。
  • 所以我应该在super.viewDidLoad()前面加上prepareForRetrieval()
  • 请阅读文章。您需要从异步代码内部进行任何后续操作。
  • @matt 我确实通读了这篇文章。您能否发布有关如何更改代码以使其正确的答案?请注意,prepareForRetrieval()updateCart() 函数位于与 ViewController 分开的结构中。

标签: ios arrays swift uitableview uitableviewdatasourceprefetching


【解决方案1】:

updateCart 中将数据附加到cartArray 后,您应该reloadData(),如下所示:

weak var tableViewOutlet: UITableView?
func updateCart() {
        for key in keyArray {
            Database.database().reference().child("UserCart").child(Auth.auth().currentUser!.uid).child(key).observeSingleEvent(of: .value, with: {
                (snapshot) in
                let value = snapshot.value as? NSDictionary
                let itemName = value?["Item Name"] as! String
                let itemPrice = value?["Item Price"] as! Float
                let itemQuantity = value?["Item Quantity"] as! Int
                self.cartArray.append(CartData(itemName: itemName, itemQuantity: itemQuantity, itemPriceNumber: itemPrice))
                DispatchQueue.main.async {
                    self.tableViewOutlet.reloadData()
                }
            })
        }
    }

updateCart 似乎与tableViewOutlet 没有任何联系,因此您需要在您的viewDidLoad 中传递对它的引用,如下所示:

override func viewDidLoad() {
    super.viewDidLoad()

    cartBrain.tableViewOutlet = tableViewOutlet
    cartBrain.prepareForRetrieval()

注意:由于您使用 for 循环多次触发异步调用,因此您可以使用数组计数来检查是否附加了所有项目以进行重新加载以避免多次重新加载。

【讨论】:

  • 此解决方案不起作用,它会导致线程 1 崩溃。
  • 当您的应用崩溃时出现什么错误?
  • 这是错误:Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee16b3f78).
  • 确保您的updateCart 方法可以访问tableViewOutlet。因此,我已对 cartBrainviewDidLoad 进行了修改,以便您的实现工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多