繁体   English   中英

在UITableViewCell中编辑自定义标签(swift 3 xcode)

[英]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子类的表作为它的单元格,每个单元格都有一个名为cellTitleLabelUILabel属性,您可以根据需要进行更改。

编辑: - 我忘了添加使用重用标识符注册单元格的部分。 在创建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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM