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

时间:2017-01-12 21:52:23

标签: swift xcode uitableview uilabel

我正在尝试研究如何编辑我添加到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"

谢谢,非常感谢任何帮助!

4 个答案:

答案 0 :(得分:0)

每次调用cellForRowAt indexPath:时都会调用tableView.reloadData()函数。

尝试将标签文本设置为变量并刷新表格。 所以......

cellTitleLabel.text = "Title"

cellTitleLabel.text = myVar

然后更新myVar并重新加载tableView数据。

如果它是一个非常大的表,您可以通过仅刷新该行或节来节省资源。

tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Top)

答案 1 :(得分:0)

我看到的问题是,当您加载单元格时,您正在创建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子类的表作为它的单元格,每个单元格都有一个名为UILabel的{​​{1}}属性,您可以根据需要进行更改。

编辑: - 我忘了添加使用重用标识符注册单元格的部分。创建tableView时,请确保添加:

cellTitleLabel

答案 2 :(得分:0)

嗯,问题是,您的解决方案在多个级别上都是错误的。 Pierce的解决方案虽然被更好地分解,但也是错误的。

您看,问题是,每次出列单元格时都会添加新的子视图,但是您永远不会从层次结构中删除子视图。这意味着您有多个子视图堆叠在另一个子视图之上。

其次,你绝对应该使用自动布局,因为你的手机在不同的设备上看起来不太好。

第三,当你开始改变某些事情时,使用强制广播是失败的一种简短方法。不惜一切代价避免使用它们,而是使用纯可选代替。

最后,但并非最不重要,我建议使用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"
    }
}

而且,让我再次强调,界面构建器是可行的方法,自动布局是绝对必须的。

答案 3 :(得分:0)

1)你的问题是你总是在每次通话时向小区添加新的protocol。您可以在3D Debug视图中看到越来越多的UILabel堆叠

2)你应该只在单元格的init中创建一次子视图和标签

3)我在表格中显示了多种类型的单元格。我创建了一个protocol UpdateableTableViewCell { func configCell(with data:MyTableDataModel) } 来将一个单元格的内部实现与调用tableViewController分离。现在您可以自由创建不同的单元格,每个单元格负责正确布局和更新内容:

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.register(MyTinyTableViewCell.self, forCellReuseIdentifier: "tinyCell")
tableView.register(MyBigTableViewCell.self, forCellReuseIdentifier: "bigCell")
tableView.register(MyImageTableViewCell.self, forCellReuseIdentifier: "imageCell")

并且不要忘记在tableView上注册所有单元格:

protocol MyTableDataModel {
    let description:String { get }
    let title:String { get }
    let imageUrl:String { get }    
}

4)为了使其更加灵活,您还可以抽象数据模型和协议,以便您可以为您的单元格使用不同的模型。

type: book
book:
  title: Dune
  author: Frank Herbert
  copyright: ${book.author} 1965
  protaganist: ${characters.0.name}
  media:
    - hardcover
characters:
  - name: Paul Atreides
    occupation: Kwisatz Haderach
    aliases:
      - Usul
      - Muad'Dib
      - The Preacher
  - name: Duncan Idaho
    occupation: Swordmaster
summary: ${book.title} by ${book.author}
product-name: ${${type}.title}