2017-01-12 1 views
1

Я пытаюсь решить, как отредактировать ярлык, который я добавил в подвью в моей ячейке UITableView. Вот код:Редактирование пользовательской метки в UITableViewCell (быстрый x xode)

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" 

Спасибо, любая помощь будет принята с благодарностью!

+0

Почему бы не создать пользовательский подкласс 'UITableViewCell'? – Pierce

ответ

0

Функция cellForRowAt indexPath: вызывается каждый раз, когда вызывается tableView.reloadData().

Попробуйте настроить текст ярлыка на переменную и обновить таблицу. Итак ...

cellTitleLabel.text = "Title" 

в

cellTitleLabel.text = myVar 

Затем обновите myVar и перезагрузить данные tableView.

Если это значительно большая таблица, вы можете сэкономить ресурсы, обновив только эту строку или раздел.

tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Top) 
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 с именем cellTitleLabel, которое вы можете изменить по мере необходимости.

EDIT: - Я забыл добавить часть, в которой вы регистрируете ячейку с идентификатором повторного использования. Когда вы создаете свой tableView, не забудьте добавить это:

tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomTableViewCell") 
+0

Я забыл добавить к этому одно, когда вы создаете таблицуView, вам нужно зарегистрировать идентификатор повторного использования ячейки «tableView.register (CustomTableViewCell.self, forCellReuseIdentifier:« CustomTableViewCell »)' Я обновлю ответ. – Pierce

0

Ну, проблема в том, что ваше решение неверно на нескольких уровнях. Решение Pierce, будучи лучше разложенным, также ошибочно.

Понимаете, проблема заключается в том, что вы добавляете новое subview каждый раз, когда вы деактивируете ячейку, но вы никогда не удаляете subview из иерархии. Это означает, что у вас есть несколько подъячейков, укладывающих один поверх другого.

Во-вторых, вы должны обязательно использовать автоспуск, так как ваша камера не будет выглядеть хорошо на разных устройствах.

В-третьих, использование силовых передач - это короткий путь к сбоям, когда вы начинаете что-то менять. Избегайте их любой ценой, используя вместо этого чистый вариант.

Последнее, но не менее важное, я рекомендую использовать 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" 
    } 
} 

И, позвольте мне еще раз подчеркнуть, интерфейс строитель способ пойти и автоспуск - это абсолютно необходимо.

0

1) Ваша проблема в том, что вы всегда добавляете новый UILabel в ячейку при каждом вызове. Вы можете увидеть это в 3D Debug посмотреть, что все больше и больше UILabel сложены

2) вы должны создать подвидов и метки только один раз в инициализации клетки

3) У меня есть более чем один тип клеток отображается в таблице. я создал , чтобы отделить внутреннюю реализацию ячейки от вызывающего 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 }  
} 
Смежные вопросы