【问题标题】:Swift Firebase UITableViewCell loads before Data to populate cell is available在填充单元格的数据可用之前加载 Swift Firebase UITableViewCell
【发布时间】:2019-03-19 02:11:47
【问题描述】:

我正在将作为字符串数组的数据推送到 tableview 控制器。这些字符串是“uid”,它们是我数据库中的用户。使用此数组,我调用 firebase 以提取所有用户,然后与 uid 进行匹配。我得到了正确的数据,但我打印出所有内容以确保数据何时可用并且数据仅在 tableview 单元加载后才可用,这导致数据为零导致崩溃或只是空数据。如何先加载数据,然后加载单元格,以便显示数据?

我已经为数据创建了函数,现在我的 viewDidLoad 中有它。此外,您会看到我已尝试将 firebase 调用添加到 Cell 设置中,但当然这不起作用。

字符串数组

var data = [String]() 

viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    Database.database().reference().child("Businesses").observe(.value, with: { snapshot in
        if snapshot.exists() {
            self.businessUID = snapshot.value as? NSDictionary
            if let dict = snapshot.value as? NSDictionary {
                for item in dict {
                    let json = JSON(item.value)
                    let businessUid = json["uid"].stringValue
                    for uid in self.data {
                        if uid == businessUid {
                            let customerValue = self.businessUID?[uid]
                            self.businessDictionary = customerValue as! NSDictionary
                            print(self.businessDictionary)
                            print("Just printed the business dictionary")
                        }
                    }
                }
            }
        } else {
            print("does not exist")
        }
    })
}

表格视图单元格

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomerViewsSelectedBusinessesCell

    print(self.businessDictionary)
    print("Print the dictionary here to check the values")
    let businessValues = self.businessDictionary
    let uid = self.data.description

    print(businessValues)
    print("printed the business values")

    if let dict = businessValues {
        for item in dict {
            let json = JSON(item.value)
            let businessUid = json["uid"].stringValue
            for uid in self.data {
                if uid == businessUid {
                    let customerValue = self.businessUID?[uid]
                    self.businessData = customerValue as? NSDictionary
                    print(self.businessData)
                    print("Printing matching the uid values")
                }
            }
        }
    }

    cell.businessName.text = businessData?["businessName"] as? String
    cell.businessStreet.text = businessData?["businessStreet"] as? String
    cell.businessCity.text = businessData?["businessCity"] as? String
    cell.businessState.text = businessData?["businessState"] as? String

    let businessProfilePicture = businessData?["profPicString"] as? String
    if (businessProfilePicture!.characters.count) > 0 {
        let url = URL(string: (businessProfilePicture!))
            DispatchQueue.global().async {
                let data = try? Data(contentsOf: url!)
                DispatchQueue.main.async {
                    let image = UIImage(data: data!)?.potter_circle
                    cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
                    cell.profileImage.image = image
                    }
                }
            } else {
        let image = UIImage(named: "default")?.potter_circle
        cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
        cell.profileImage.image = image
    }

    return cell
}

【问题讨论】:

  • 嗨弗兰克,很高兴再次在我的帖子中见到你。也许我只需要创建一个数据结构,然后将所需的数据应用到它上面。我仍然很好奇当前的问题是否可以解决。
  • 对所有这些来说都是新的(这就是为什么这不是一个答案,而是一个建议),但我认为 Database 闭包中的东西是异步的。正因为如此,我认为一旦你将所有数据从火力基地中取出并进入你的控制器,你就需要在 tableview 上调用reloadData()。这将使表视图重新呈现,因为它现在知道其数据源中的数据已更改。另外,我没有看到您实际上将 var data 设置为任何内容。我看到你循环它,但没有设置它。你确定这是对的吗?
  • 有道理,我会试一试。我不需要设置“var data”,只使用内部的 uid 进行匹配,然后获取所有用户数据并将其应用于字典。
  • 是的,重新加载 tableview 并没有这样做,因为从一开始就没有技术上的数据,所以它会崩溃或什么都不显示,因为字典在技术上仍然是 nil
  • 所以我们在同一页面上,您在设置businessData 之后立即调用reloadData()?如果是这样,您能否发布数据源方法,例如 numberOfRowsInSection 方法?

标签: ios swift firebase uitableview firebase-realtime-database


【解决方案1】:

这是我的解决方案。让它工作。附加并使用“usersArray”来获取和显示数据。

var data = [String]()
var usersArray = [NSDictionary?]()


override func viewDidLoad() {
    super.viewDidLoad()

    Database.database().reference().child("Businesses").observe(.value, with: { snapshot in
        if snapshot.exists() {
            self.businessUID = snapshot.value as? NSDictionary
            if let dict = snapshot.value as? NSDictionary {
                for item in dict {
                    let json = JSON(item.value)
                    let businessUid = json["uid"].stringValue
                    for uid in self.data {
                        if uid == businessUid {
                            let customerValue = self.businessUID?[uid]
                            self.usersArray.append(customerValue as! NSDictionary)
                            self.followUsersTableView.reloadData()
                        }
                    }
                }
            }
        } else {
            print("does not exist")
        }
    })
}


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

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.usersArray.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomerViewsSelectedBusinessesCell

    let user : NSDictionary?

    user = self.usersArray[indexPath.row]

    cell.businessName.text = String(user?["businessName"] as! String)
    cell.businessStreet.text = String(user?["businessStreet"] as! String)
    cell.businessCity.text = String(user?["businessCity"] as! String)
    cell.businessState.text = String(user?["businessState"] as! String)

    let businessProfilePicture = String(user?["profPicString"] as! String)
    if (businessProfilePicture.characters.count) > 0 {
        let url = URL(string: (businessProfilePicture))
            DispatchQueue.global().async {
                let data = try? Data(contentsOf: url!)
                DispatchQueue.main.async {
                    let image = UIImage(data: data!)?.potter_circle
                    cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
                    cell.profileImage.image = image
                    }
                }
            } else {
        let image = UIImage(named: "default")?.potter_circle
        cell.profileImage.contentMode = UIView.ContentMode.scaleAspectFill
        cell.profileImage.image = image
    }

    return cell
}

【讨论】:

  • 为什么不能从循环中重新加载数据?在循环中重新加载数据只会增加处理时间和应用程序效率,这也是一种不好的方法。
  • 另外这个视图控制器不会被大量使用,但我仍然想学习如何提高速度和减少内存。
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 2019-06-11
  • 1970-01-01
  • 2017-10-08
  • 1970-01-01
  • 2016-10-26
相关资源
最近更新 更多