![](/img/trans.png)
[英]how to recognize label click on custom UITableViewCell - Swift 3
[英]Editing custom label in UITableViewCell (swift 3 xcode)
我正在尝试研究如何编辑我添加到UITableView单元格中的子视图的标签。 这是代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
var cellTitleLabel = UILabel(frame: CGRect(x: 45,y: 2,width: 100,height: 20))
cellTitleLabel.textAlignment = NSTextAlignment.left
cellTitleLabel.text = "Title"
cellTitleLabel.font = UIFont(name: "Swiss721BT-Roman", size: 16)
cell.addSubview(cellTitleLabel)
return cell
}
现在我希望能够将字符串从“标题”更改为任何内容,但似乎我可以更新该文本的唯一方法是删除子视图,然后添加一个更新参数的新视图。 是不是可以做这样的事情:
cell.cellTitleLabel.text = "New Title"
谢谢,任何帮助将不胜感激!
每次调用tableView.reloadData()
都会调用cellForRowAt indexPath:
函数。
尝试将标签文本设置为变量并刷新表格。 所以...
cellTitleLabel.text = "Title"
至
cellTitleLabel.text = myVar
然后更新myVar
并重新加载tableView
数据。
如果它是一个非常大的表,您可以通过仅刷新该行或节来节省资源。
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Top)
我看到的问题是,当您加载单元格时,您正在创建UILabel
作为单元格的子视图,但您没有保留对该标签的任何引用。 因此,单元格在初始化后不再具有任何名为cellTitleLabel
属性。
我建议创建一个自定义的UITableViewCell
子类,如下所示:
import UIKit
class CustomTableViewCell: UITableViewCell {
var cellTitleLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization Code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setCellContent(text: String) {
let cellTitleLabel = UILabel(frame: CGRect(x: 45,y: 2,width: 100,height: 20))
cellTitleLabel.textAlignment = NSTextAlignment.left
cellTitleLabel.text = text
cellTitleLabel.font = UIFont(name: "Swiss721BT-Roman", size: 16)
self.addSubview(cellTitleLabel)
self.cellTitleLabel = cellTitleLabel
}
}
然后在设置时调用cellForRowAtIndexPath
,可以实例化自定义单元格
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell
cell.setCellContent(text: "Cell Title")
return cell
}
然后你会有一个充满CustomTableViewCell
子类的表作为它的单元格,每个单元格都有一个名为cellTitleLabel
的UILabel
属性,您可以根据需要进行更改。
编辑: - 我忘了添加使用重用标识符注册单元格的部分。 在创建tableView时,请确保添加以下内容:
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomTableViewCell")
嗯,问题是,你的解决方案在多个层面上是错误的。 皮尔斯的解决方案虽然被更好地分解,但也是错误的。
您看,问题是,每次出列单元格时都会添加新的子视图,但是您永远不会从层次结构中删除子视图。 这意味着您有多个子视图堆叠在另一个子视图之上。
其次,你绝对应该使用autolayouts,因为你的手机在不同的设备上看起来不太好。
第三,当你开始改变某些事情时,使用强制播放是一种很短的失败方法。 不惜一切代价避免使用它们,而是使用纯可选。
最后,但并非最不重要,我建议使用Interface Builder来创建视图布局和层次结构。
至于解决方案,如果您创建了以下形式的单元子类,那么您的解决方案会好得多:
class CustomTableViewCell: UITableViewCell {
var titleLabel: UILabel? {
didSet {
titleLabel.map { self.addSubview($0) }
oldValue?.removeFromSuperview()
}
}
override func awakeFromNib() {
super.awakeFromNib()
let label = UILabel(frame: CGRect(x: 45,y: 2,width: 100,height: 20))
label.textAlignment = NSTextAlignment.left
label.font = UIFont(name: "Swiss721BT-Roman", size: 16)
self.titleLabel = label
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let cell = cell as? CustomTableViewCell {
cell.titleLabel?.text = "Title"
}
return cell
}
}
但是,为了进一步改进它,我建议使用IDPCastable cocoapod等东西
它允许您在没有强制转换的情况下简化匹配:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return match(cell) { (c: CustomTableViewCell) in
c.titleLabel?.text = "Title"
}
}
而且,让我再次强调,界面构建器是要走的路,自动布局是绝对必须的。
1)你的问题是你总是在每次通话时向单元格添加新的UILabel
。 你可以在3D Debug视图中看到越来越多的UILabel被堆叠
2)您应该只在单元格的init中创建一次子视图和标签
3)我在表格中显示了多种类型的单元格。 我创建了一个protocol
来解密单元格的内部实现与调用tableViewController。 现在您可以自由创建不同的单元格,每个单元格负责正确的布局和内容更新:
protocol UpdateableTableViewCell {
func configCell(with data:MyTableDataModel)
}
现在我所有不同的单元格实现了这个协议
class MyTinyTableViewCell: UITableViewCell, UpdateableTableViewCell {
let cellTitleLabel = UILabel()
//[...]
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
func setup() {
cellTitleLabel.frame = : CGRect(x: 45,y: 2,width: 100,height: 20))
cellTitleLabel.textAlignment = NSTextAlignment.left
cellTitleLabel.font = UIFont(name: "Swiss721BT-Roman", size: 16)
self.contenView.addSubview(cellTitleLabel)
}
// implement protocol UpdateableTableViewCell
func configCell(with data:MyTableDataModel){
resetCell()
cellTitleLabel.text = data.description
}
///[...]
func resetCell(){
// reset here all other cell ui elements to default values
}
}
现在我可以一步重复使用不同的单元格:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellData:MyTableDataModel = myDataArray(indexPath.row)
// calculate the celltype depending on the current data in the cell
let cellTypeIdentifier = getCellTypeIdentifier(cellData)
if let cell = tableView.dequeueReusableCell(withIdentifier: cellTypeIdentifier, for: indexPath) as UpdateableTableViewCell {
cell.configCell(with: cellData)
}
}
并且不要忘记在tableView上注册所有单元格:
tableView.register(MyTinyTableViewCell.self, forCellReuseIdentifier: "tinyCell")
tableView.register(MyBigTableViewCell.self, forCellReuseIdentifier: "bigCell")
tableView.register(MyImageTableViewCell.self, forCellReuseIdentifier: "imageCell")
4)为了使它更灵活,您还可以抽象数据模型和协议,以便您可以为您的单元格使用不同的模型。
protocol MyTableDataModel {
let description:String { get }
let title:String { get }
let imageUrl:String { get }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.