在 UITableView 中正确显示 JSON 数据

Posted

技术标签:

【中文标题】在 UITableView 中正确显示 JSON 数据【英文标题】:Show JSON data correctly in UITableView 【发布时间】:2017-09-19 07:40:01 【问题描述】:

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

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

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

【问题讨论】:

你做错了,你应该创建一个单独的类来继承 UITableViewCell 并在那里添加所有控件,这种创建单元格的方式是不正确的 @Winn Stone :那是因为单元格被重复使用并且超时你添加标签和图像而不检查它是否已经添加到单元格 【参考方案1】:

您在使可重用单元出列时多次添加子视图。您可以做的是在情节提要或 xib 文件中制作原型单元格,然后在 cellForRowAtIndexPath 处将该单元格出列。

您的单元格自定义类将类似于从原型单元格中绘制出口的情况。

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

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

现在您可以对 DemoProtoTypeCell 进行 deque 并相应地使用。

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

【讨论】:

【参考方案2】:

那是因为您正在将子视图添加到重用(因此它可能已经有之前添加的子视图)单元格。

尝试检查单元格是否有子视图并填写您需要的信息,如果没有子视图则将它们添加到单元格中。

选项 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 子类已经拥有你需要的所有子视图。

【讨论】:

【参考方案3】:

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

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()
         
    

希望这会有所帮助。

【讨论】:

【参考方案4】:

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

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

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

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

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

【讨论】:

【参考方案5】:

试试这个:

    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
    

【讨论】:

以上是关于在 UITableView 中正确显示 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 没有正确拉入 JSON

JSON 数据未显示在 UITableView 上

将 Json 解析为 UITableview

在 UITableView 中显示 JSON 数据

在 UITableView 中显示 Json 结果

在 UITableView 中显示来自 JSON 的数据