2017-01-12 3 views
1

UITableView 셀 내에서 서브 뷰에 추가 한 레이블을 편집하는 방법을 알아 내려고합니다. 여기에 코드입니다 :UITableViewCell (swift 3 xcode)에서 사용자 정의 레이블 편집

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이라는 속성을 갖지 않습니다. 그런 다음

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell") as! CustomTableViewCell 
    cell.setCellContent(text: "Cell Title") 

    return cell 
} 

당신이 가진 거라고는 cellForRowAtIndexPath를 호출 할 때 당신에게 설치 그런 다음, 사용자 정의 셀을 인스턴스화 할 수

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 

    } 


} 

을 :

나는 정의 UITableViewCell 서브 클래스, 이런 식으로 뭔가를 만드는 제안 CustomTableViewCell 서브 클래스가 셀로 채워진 표가 있으며, 각 셀에는 UILabel이라는 속성이 있으며, 필요에 따라 변경할 수 있습니다. cellTitleLabel.

편집 : - 재사용 식별자가있는 셀을 등록하는 부분을 추가하는 것을 잊었습니다. tableView를 만들 때 다음을 추가하십시오.

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

tableView.register (CustomTableViewCell.self, forCellReuseIdentifier : "CustomTableViewCell")'셀의 재사용 식별자를 등록해야하는 tableView를 만들 때이 점에 하나의 것을 추가하는 것을 잊어 버렸다. – Pierce

0

글쎄, 문제는 여러 단계에서 솔루션이 잘못되었다는 것입니다. Pierce의 해법은 더 잘 분해되지만 잘못된 것입니다.

셀을 대기열에서 제거 할 때마다 새 하위보기를 추가하지만 계층 구조에서 하위 뷰를 제거하지 않는 것이 문제입니다. 이것이 의미하는 바는 다른 서브 뷰 위에 여러 개의 서브 뷰가 쌓여 있다는 것입니다.

두 번째로 셀이 다른 장치에서 잘 보이지 않으므로 자동 레이아웃을 사용해야합니다.

셋째, 무언가를 변경하기 시작할 때 forcecast를 사용하면 실패 할 수있는 짧은 방법입니다. 순수한 옵션을 대신 사용하여 피하십시오.

마지막으로 인터페이스 레이아웃을 사용하여 뷰 레이아웃과 계층 구조를 만드는 것이 좋습니다.

그러나
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" 
    } 
} 

을 그리고 :

그것은 힘이 캐스트없이 당신이 일치를 단순화 할 수 있도록 할 가는 길과 autolayouts 절대적으로해야합니다.

0

1) 문제가 발생하면 각 통화시 항상 새 UILabel을 셀에 추가해야합니다. 당신은 3D 디버그에서 볼 수 있습니다 당신은 셀

3) 내가 셀의 두 개 이상의 유형이의 초기화에 한 번만 파단 및 레이블을 만들어야합니다) 더 많은 UILabel의이

2

을 적층되어 있음을 볼 수 테이블에 표시됩니다. 난 호출 tableViewController에서 세포의 내부 구현을 decouple 만들었습니다. 지금 당신은 다른 세포를 만들 무료이며 각 셀 콘텐츠의 오른쪽 레이아웃 및 업데이트에 대한 책임 :

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 
    } 
} 

지금 내가 다른 재사용 할 수 있습니다 : 지금 내 모든 다른 세포가이 프로토콜을 구현

protocol UpdateableTableViewCell { 
    func configCell(with data:MyTableDataModel) 
} 

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 }  
} 
관련 문제