2017-09-19 103 views
0

我制作了一个UITableView,并在JSON数据中填充了我在API中获得的数据。我得到并正确放置,但当我滚动或删除一行时,一切都变得混乱!在UITableView中正确显示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 
} 
+0

你正在做的都错了,你应该继承的UITableViewCell创建一个单独的类,并添加有所有的控制,这样一来,用于创建细胞是不正确的 –

+0

@Winn石:那是因为细胞得到重用和加班ü添加标签和图像,而不检查它是否已经添加到单元格 –

回答

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! }

可以双端队列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 
} 
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个

克里特UITableViewCell子类,已经拥有你需要的所有子视图。

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

希望这有助于。

0

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

但我想解释为什么你会得到这种奇怪的行为。

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

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

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

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 
    }