【问题标题】:Swift: Table View is only returning one cellSwift:表格视图只返回一个单元格
【发布时间】:2017-09-23 03:50:27
【问题描述】:

我正在尝试加载具有两个不同原型单元格的表格视图。 profileCell 应该只加载一次并且在表格视图的顶部。 dogCell 应该计算从 firebase 下载的名为 dogsdog 对象数组。目前,只有第一个单元格显示正确。

我认为numberOfRowsInSection 方法不能准确计算 dog 数组中的 dog 对象。当我在return dogs.count + 1po dogs.count 上设置断点时,调试器会一直输出0

当我使用return dogs.count 时,表格视图会加载,但只有配置文件单元格。如果我使用return dogs.count + 1(考虑顶部的配置文件单元格)构造dogCell时会引发异常:“致命错误:索引超出范围”

也许我需要改变我的 tableview 重新加载数据的方式?

这是我的代码:

class DogTableViewController: UITableViewController {

    var user = User()
    let profileCell = ProfileTableViewCell()
    var dogs = [Dog]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let userDogRef = Database.database().reference().child("users").child(user.uid!).child("dogs")

        let userProfileImageView = UIImageView()
        userProfileImageView.translatesAutoresizingMaskIntoConstraints = false
        userProfileImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
        userProfileImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
        userProfileImageView.layer.cornerRadius = 20
        userProfileImageView.clipsToBounds = true
        userProfileImageView.contentMode = .scaleAspectFill
        userProfileImageView.image = UIImage(named: "AppIcon")

        navigationItem.titleView = userProfileImageView

        //MARK: Download dogs from firebase
        userDogRef.observe(.childAdded, with: { (snapshot) in
            if snapshot.value == nil {
                print("no new dog found")
            } else {
                print("new dog found")

                let snapshotValue = snapshot.value as! Dictionary<String, String>
                let dogID = snapshotValue["dogID"]!

                let dogRef = Database.database().reference().child("dogs").child(dogID)
                dogRef.observeSingleEvent(of: .value, with: { (snap) in
                    print("Found dog data!")
                    let value  = snap.value as? NSDictionary
                    let newDog = Dog()

                    newDog.name = value?["name"] as? String ?? ""
                    newDog.breed = value?["breed"] as? String ?? ""
                    newDog.creator = value?["creator"] as? String ?? ""
                    newDog.score = Int(value?["score"] as? String ?? "")
                    newDog.imageURL = value?["imageURL"] as? String ?? ""
                    newDog.dogID = snapshot.key

                    URLSession.shared.dataTask(with: URL(string: newDog.imageURL!)!, completionHandler: { (data, response, error) in
                        if error != nil {
                            print(error!)
                            return
                        }
                        newDog.picture = UIImage(data: data!)!
                        self.dogs.append(newDog)
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                        }
                    }).resume()
                })
            }
        })

        tableView.estimatedRowHeight = 454
    }

    // MARK: - Table view data source

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dogs.count + 1
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let profileCell = tableView.dequeueReusableCell(withIdentifier: "profileCell", for: indexPath) as! ProfileTableViewCell
            profileCell.nameLabel.text = user.name
            profileCell.totalReputationLabel.text = String(describing: user.reputation!)
            profileCell.usernameLabel.text = user.username
            return profileCell
        } else {
            let dogCell = tableView.dequeueReusableCell(withIdentifier: "dogCell", for: indexPath) as! DogTableViewCell
            dogCell.dogBreedLabel.text = dogs[indexPath.row].breed
            dogCell.dogNameLabel.text = dogs[indexPath.row].name
            dogCell.dogScoreLabel.text = String(describing: dogs[indexPath.row].score)
            dogCell.dogImageView.image = dogs[indexPath.row].picture
            dogCell.dogCreatorButton.titleLabel?.text = dogs[indexPath.row].creator
            dogCell.dogVotesLabel.text = "0"
            return dogCell
        }

    }
}

【问题讨论】:

  • 如果你(正确地)在tableView(_, cellForRowAt:)中动态获取单元格,为什么你在viewDidLoad()中有一个profileCell局部变量?
  • 您是否验证了从数据库返回的狗的预期数量?
  • @NRitH 不错!我不知道为什么类中有一个配置文件单元格属性。我会删除它。是的,我已经确认狗被正确归还。感谢您的帮助。

标签: ios swift uitableview firebase


【解决方案1】:

其实我在写完这个问题后不久就找到了解决方案,但我认为它可能对其他人阅读有所帮助。

因为第一个 indexPath.row 专用于配置文件单元格,所以我不应该使用 indexPath.row 来导航我的 dogs 数组。相反,我应该使用indexPath.row - 1 来获得正确的狗指数。

这是我更新的部分:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let profileCell = tableView.dequeueReusableCell(withIdentifier: "profileCell", for: indexPath) as! ProfileTableViewCell
            profileCell.nameLabel.text = user.name
            profileCell.totalReputationLabel.text = String(describing: user.reputation!)
            profileCell.usernameLabel.text = user.username
            return profileCell
        } else {
            let dogCell = tableView.dequeueReusableCell(withIdentifier: "dogCell", for: indexPath) as! DogTableViewCell
            dogCell.dogBreedLabel.text = dogs[indexPath.row - 1].breed
            dogCell.dogNameLabel.text = dogs[indexPath.row - 1].name
            dogCell.dogScoreLabel.text = String(describing: dogs[indexPath.row - 1].score)
            dogCell.dogImageView.image = dogs[indexPath.row - 1].picture
            dogCell.dogCreatorButton.titleLabel?.text = dogs[indexPath.row - 1].creator
            dogCell.dogVotesLabel.text = "0"
            return dogCell
        }

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多