问题描述
我有 UITableView、UITablaViewCell、CustomView
和 UITableViewCell 包括 customView。
我正在尝试使用我的函数而不是 cellForRowAt 将产品的数据放入单元格。
单元格仅显示带有空数据的原始视图 ProductView.xib
请帮忙。
ViewController.swift
struct Product {
let brand: String
let product: String
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell",for: indexPath) as! ProductTableViewCell
// this line is not work
// productView is not update
cell.productView = createProductView(product: product)
return cell
}
func createProductView(product: Product) -> ProductView {
let productView = ProductView()
productView.brandLabel.text = product.brand
productView.productLabel.text = product.product
return productView
}
UITableViewCell.swift
class ProductTableViewCell: UITableViewCell {
@IBOutlet var productView: ProductView!
}
ProductView.swift
class ProductView: UIView {
@IBOutlet weak var productView: UIView!
@IBOutlet weak var brandLabel: UILabel!
@IBOutlet weak var productLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit(){
let bundle = Bundle(for: ProductView.self)
bundle.loadNibNamed("ProductView",owner: self,options: nil)
addSubview(productView)
productView.frame = self.bounds
}
解决方法
您的代码存在多个问题
问题 1: cellForRowAt IndexPath
被多次调用,使用您的代码,每次滚动 tableView(单元格被重用)时,您最终都会创建一个新的 ProductView
。相反,您只能创建一次产品视图并在每次重复使用单元格时更新其标签
问题 2:在 ProductView
的 commonInit 中,您使用 productView.frame = self.bounds
self.bounds will always be(0,0) 设置框架。因为您已将 ProductView 实例化为 ProductView()
问题 3: createProductView
应该返回 ProductView
的实例,因此方法签名无效,因此您应该将其从 func createProductView(product: Product) -> ProductView()
更改为 {{ 1}} 正如上面的回答中已经建议的
什么是更好的解决方案?
func createProductView(product: Product) -> ProductView
终于在您的 class ProductTableViewCell: UITableViewCell {
var productView: ProductView!
func updateProductView(product: Product) {
productView.brandLabel.text = product.brand
productView.productLabel.text = product.product
}
override func prepareForReuse() {
super.prepareForReuse()
productView.brandLabel.text = nil
productView.productLabel.text = nil
}
override func awakeFromNib() {
super.awakeFromNib()
self.productView = createProductView()
self.addSubview(self.productView)
self.productView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.productView.leadingAnchor.constraint(equalTo: self.leadingAnchor),self.productView.trailingAnchor.constraint(equalTo: self.trailingAnchor),self.productView.topAnchor.constraint(equalTo: self.topAnchor),self.productView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
}
func createProductView() -> ProductView {
return ProductView()
}
}
cellForRowAtIndexPath
编辑:
由于 OP 面临从包中加载笔尖的问题,请在此处更新答案。
在您的 func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell",for: indexPath) as! ProductTableViewCell
//assuming you already have a product for index path
cell.updateProductView(product: product)
return cell
}
common init 中更改您访问 bundle 的方式
ProductView
到 Bundle(for: ProductView.self)
如下图
Bundle.main
需要注意的事项
- 确保您的捆绑包中有一个名为
class ProductView: UIView { @IBOutlet weak var productView: UIView! @IBOutlet weak var brandLabel: UILabel! @IBOutlet weak var productLabel: UILabel! override init(frame: CGRect) { super.init(frame: frame) commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } private func commonInit(){ Bundle.main.loadNibNamed("ProductView",owner: self,options: nil) addSubview(productView) }
的 XIB - 确保您已将其文件所有者设置为
ProductView