코드에서 커스텀 셀을 사용할 때 register(_:forCellReuseIdentifier:) 함수를 넣었다

16542 단어 XcodeUIKitSwift4

전제



Xcode9.2
Swift4

문제



열별로 표시할 셀을 결정하는 델리게이트 메서드를 작성하여 해당 열에 어떤 셀을 사용할지 결정합니다.
extension ListViewController: UITableViewDelegate, UITableViewDataSource {

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(ListTableViewCell.self), for: indexPath) as? ListTableViewCell else {
            fatalError("The dequeued cell is not instance of MealTableViewCell.")
        }

///ここ以下省略

여기서 떨어진다.
guard let cell = tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(ListTableViewCell.self), for: indexPath) as? ListTableViewCell

오류 메시지


reason: 'unable to dequeue a cell with identifier Todolist_firebase.MyCell - 
must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

원인과 해결책



아래의 넣어 잊어
tableView.register(ListTableViewCell.self, forCellReuseIdentifier: NSStringFromClass(ListTableViewCell.self))

register(_,identifier)의 Apple 공식 문서 에서는 여기서 소개되고 있습니다
func register(_ cellClass: AnyClass?, 
forCellReuseIdentifier identifier: String)
セルを作成する前に、このメソッド(_:forCellReuseIdentifier :)を呼び出して、新しいセルをつくることをテーブルビューに伝えます。 指定されたタイプのセルが現在再利用キューにない場合、テーブルビューは提供された情報を使用して新しいセルオブジェクトを自動的に作成します。

즉 제1 인수에는 이 테이블 뷰로 사용하는 cell의 클래스를 등록해, 제2 인수에서는 재이용할 때의 명찰적인 서 위치에서 String형의 이름을 넣어 주세요라고 하는 것일까요

dequeueReusableCell(withIdentifier:for:)의 Apple 공식 문서
재사용 가능한 테이블 뷰 셀 객체를 반환하고 테이블에 추가하는 함수입니다.
이 함수는 제 1 인수가 String 형의 identifier 로 제 2 인수가 indexPath 이므로 몇번째의 셀을 대상으로 하고 있는가 하는 숫자가 돌려줍니다
제 1 인수에 주목하면 형태는 String형으로 되어 있어, 상기의 register 함수로 string로 등록한 것을 재이용할 수 있도록(듯이) 하고 있군요
func dequeueReusableCell(withIdentifier identifier: String, 
                     for indexPath: IndexPath) -> UITableViewCell

공식 문서에서는 일부러 노란색으로 둘러싸인 Important에서

重要

このメソッドを呼び出す前に、register(_:forCellReuseIdentifier :)またはregister(_:forCellReuseIdentifier :)メソッドを使用してクラスまたはnibファイルを登録する必要があります。

라고 썼습니다.

코드 전체



부분 생략
덧붙여서 왜 register 함수의 제 2 인수로 NSStringFromClass(ListTableViewCell.self) 이렇게 하고 있는가 하면, NSStringFromClass 함수는 인수로 넣은 클래스를 String으로 해 돌려주는 함수이기 때문입니다
例
NSStringFromClass(ListTableViewCell.self)
↓
"Todolist_firebase.ListTableViewCell"
class ListViewController: UIViewController {
    var tableView = UITableView()
    override func viewDidLoad() {
        super.viewDidLoad()

        //テーブルビュー
        tableView = UITableView(frame: self.view.frame, style: .plain)
        tableView.rowHeight = 100
        tableView.delegate = self
        tableView.dataSource = self
        //NSStrignFromClassはクラスの名前をStringで返してくれる
        tableView.register(ListTableViewCell.self, forCellReuseIdentifier: NSStringFromClass(ListTableViewCell.self))
        self.view.addSubview(tableView)
    }

}

extension ListViewController: UITableViewDelegate, UITableViewDataSource {

    //セクションの数を設定
    func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    //行数 セクションによって行数が違う場合はsectionで場合分けをするUITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }
    //列ごとに表示するセルを決めるデリゲートメソッド
    //UITableViewDataSource は主に Table View が表示するデータを与えるものです。
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(ListTableViewCell.self), for: indexPath) as? ListTableViewCell else {
            fatalError("The dequeued cell is not instance of MealTableViewCell.")
        }

        let item = items[indexPath.row]
        cell.nameLabel.text = item.title     
        return cell
    }
}

class ListTableViewCell: UITableViewCell {

    //MARK: Properties
    var nameLabel: UILabel!

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.commonInit() 
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func prepareForReuse() {
        super.prepareForReuse()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.addSubview(nameLabel)
        nameLabel.frame = CGRect(x: 110, y: 0, width: frame.width - 100, height: frame.height)

    }

    //MARK : method
    private func commonInit() {
        self.createNameLabel()
    }
    private func createNameLabel() {
        nameLabel = UILabel(frame: CGRect.zero)
        nameLabel.textAlignment = .left
        nameLabel.font = UIFont.systemFont(ofSize: 20)
    }


}



애플 문서 가라앉다
指定した識別子のクラスを登録し、新しいセルを作成する必要がある場合、init(style:reuseIdentifier :)メソッドを呼び出してセルを初期化します。 
既存のセルが再利用可能な場合、このメソッドは代わりにセルのprepareForReuse()メソッドを呼び出します。

라고 하는 것으로, prepareForReuse() 함수가 언제 사용되는지가 문서를 확인하는 것으로 알았습니다

좋은 웹페이지 즐겨찾기