如何使用 Swift 在 UITableViewCell 中设置 customView
How to set customView in UITableViewCell with Swift
我有 UITableView、UITablaViewCell、CustomView
并且 UITableViewCell 包含 customView。
我正在尝试使用我的函数而不是 cellForRowAt 将 Product 的数据放入单元格。
单元格仅显示原始视图 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 将始终为 (0,0, 0,0).因为您已将 ProductView 实例化为 ProductView()
问题 3: createProductView
应该是 return ProductView
的实例,因此方法签名无效,因此您应该更改它从 func createProductView(product: Product) -> ProductView()
到 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
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
}
编辑:
由于 OP 在从包中加载 nib 时遇到问题,请在此处更新答案。
在你的 ProductView
common init 中改变你访问 bundle 的方式
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)
}
需要注意的事项
- 确保您的包中有一个名为
ProductView
的 XIB
- 确保您已将其文件所有者设置为
ProductView
我有 UITableView、UITablaViewCell、CustomView
并且 UITableViewCell 包含 customView。
我正在尝试使用我的函数而不是 cellForRowAt 将 Product 的数据放入单元格。
单元格仅显示原始视图 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 将始终为 (0,0, 0,0).因为您已将 ProductView 实例化为 ProductView()
问题 3: createProductView
应该是 return ProductView
的实例,因此方法签名无效,因此您应该更改它从 func createProductView(product: Product) -> ProductView()
到 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
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
}
编辑:
由于 OP 在从包中加载 nib 时遇到问题,请在此处更新答案。
在你的 ProductView
common init 中改变你访问 bundle 的方式
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)
}
需要注意的事项
- 确保您的包中有一个名为
ProductView
的 XIB - 确保您已将其文件所有者设置为
ProductView