在UITableView中正确显示JSON数据

时间:2017-09-19 07:40:02

标签: ios arrays json swift uitableview

我已经创建了一个UITableView并用我在API中获得的JSON数据填充它。我得到并正确放置但是当我滚动或删除一行时,一切都搞砸了!

Take a look at the screenshot

标签和图像干扰;这是我的代码:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    var dict = productsArrayResult[indexPath.row]

    let cellImage = UIImageView(frame: CGRect(x: 5, y: 5, width: view.frame.size.width / 3, height: 90))
    cellImage.contentMode = .scaleAspectFit
    let productMainImageString = dict["id"] as! Int
    let url = "https://example.com/api/DigitalCatalog/v1/getImage?id=\(productMainImageString)&name=primary"
    self.downloadImage(url, inView: cellImage)
    cell.addSubview(cellImage)

    let cellTitle = UILabel(frame: CGRect(x: view.frame.size.width / 3, y: 5, width: (view.frame.size.width / 3) * 1.9, height: 40))
    cellTitle.textColor = UIColor.darkGray
    cellTitle.textAlignment = .right
    cellTitle.text = dict["title"] as? String
    cellTitle.font = cellTitle.font.withSize(self.view.frame.height * self.relativeFontConstantT)
    cell.addSubview(cellTitle)

    let cellDescription = UILabel(frame: CGRect(x: view.frame.size.width / 3, y: 55, width: (view.frame.size.width / 3) * 1.9, height: 40))
    cellDescription.textColor = UIColor.darkGray
    cellDescription.textAlignment = .right
    cellDescription.text = dict["description"] as? String
    cellDescription.font = cellDescription.font.withSize(self.view.frame.height * self.relativeFontConstant)
    cell.addSubview(cellDescription)

    return cell
}

5 个答案:

答案 0 :(得分:1)

您在重复使用可重复使用的单元格时多次添加子视图。你可以做的是在storyboard或xib文件中创建一个原型单元格,然后在cellForRowAtIndexPath中将该单元格出列。

Design Prototype cell and assgin with the custom class

您的单元格自定义类看起来与此类似,其中出口是从原型单元格中提取的。

注意:您需要为该原型单元分配可重用标识符。

class DemoProtoTypeCell: UITableViewCell { @IBOutlet var titleLabel: UILabel! @IBOutlet var descriptionLabel: UILabel! @IBOutlet var titleImageView: UIImageView! }

现在你可以deque DemoProtoTypeCell并相应地使用。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: DemoProtoTypeCell.self), for: indexPath) as! DemoProtoTypeCell
  cell.titleImageView.image = UIImage(named: "demoImage")
  cell.titleLabel.text = "demoTitle"
  cell.descriptionLabel.text = "Your description will go here."
  return cell
}

答案 1 :(得分:0)

那是因为您要添加子视图以供重复使用(以便它可能已经添加了以前添加的子视图)。

尝试检查单元格是否包含子视图并填写所需信息,如果没有子视图,则将其添加到单元格中。

选项1

if let imageView = cell.viewWithTag(1) {
    imageView.image = //your image
} else {
    let imageView = UIImageView(//with your settings)
    imageView.tag = 1
    cell.addSubview(imageView)
}

选项2

Crete UITableViewCell子类已经拥有您需要的所有子视图。

答案 2 :(得分:0)

我使用了以下方法从单元格中删除所有子视图:

override func prepareForReuse() {
    for views in self.subviews {
        views.removeFromSuperview()
    }
}

但是我创建了UITableViewCell子类并在其中声明了这个方法。

你也可以像@sCha所建议的那样做一件事。将标记添加到子视图,然后使用相同的方法从单元格中删除子视图:

override func prepareForReuse() {
    for view in self.subviews {
        if view.tag == 1 {
          view.removeFromSuperview()
        } 
    }
}

希望这有帮助。

答案 3 :(得分:0)

我认为其他答案已经提到了一个解决方案。您应该子类化tableview单元格,只需更改每行的布局元素的值。

但我想解释一下为什么会出现这种奇怪的行为。

打电话的时候 tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) 它尝试使用传递的标识符@"cell"重用已创建的单元格。这样可以节省内存并优化性能。如果不可能,它会创建一个新的。

所以现在我们已经有了一个布局元素的单元格,并且已经填充了您的数据。然后,您的代码会在旧代码之上添加新元素。这就是为什么你的布局搞砸了。它只显示你是否滚动,因为第一个单元格没有先前的单元格加载。

当您对单元格进行子类化时,尝试在首次初始化时仅创建一次布局。现在,您可以将所有值传递给相应的布局元素,并让tableview完成它的工作。

答案 4 :(得分:0)

试试这个:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell:UITableViewCell! = tableView.dequeueReusableCell(withIdentifier: "cell")
        if cell == nil
        {
            cell = UITableViewCell.init(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
        }
        for subView in cell.subviews
        {
            subView.removeFromSuperview()
        }
// Your Code here
    return cell
    }