68143


以下のコードのCellの部分を別のCustomCell.swiftなどで実装したいのですが、どうすればよいのでしょうか？

[code]

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = UITableViewCell()
            let rp = repo[indexPath.row]
            cell.textLabel?.text = rp["full_name"] as? String ?? ""
            cell.detailTextLabel?.text = rp["language"] as? String ?? ""
            cell.tag = indexPath.row
            return cell
    }
    
[/code]


CC BY-SA 4.0
2020-06-30T08:42:23.930
68141
2020-06-30T09:17:40.057
40856
question
swift
TableViewのCellを別クラスに移行したい


そもそもの元のコードですが、`tableView(_:cellForRowAt:)`の中で、`let cell =
UITableViewCell()`のようにセルクラス(今の場合は、`UITableViewCell`クラス)のイニシャライザを使ってセルのインスタンスを生成するのは、「誤り」と言ってしまって良いでしょう。

コンパイルエラーも実行時エラーも出ないのでやってしまいがちなのですが、システムに大きな負荷をかけ、スクロールにもやたらと時間がかかったりするようになります。

`tableView(_:cellForRowAt:)`の中でセルのインスタンスを取得する場合、必ず`dequeueReusableCell(withIdentifier:for:)`、または`dequeueReusableCell(withIdentifier:)`のどちらかのメソッドを使用して下さい。

CustomCell.swiftに`CustomCell`と言うクラスが定義してあるとすると、例えば次のようになります。

[code]

        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
            let rp = repo[indexPath.row]
            cell.textLabel?.text = rp["full_name"] as? String ?? ""
            cell.detailTextLabel?.text = rp["language"] as? String ?? ""
            cell.tag = indexPath.row
            return cell
        }
    
[/code]

(実際のカスタムセルの場合、`textLabel`やら`detailTextLabel`やらは、適切なプロパティ名に変えてやる必要があるでしょう。)

ちなみに危険な強制キャスト`as!`を使っていますが、これは「もし設定が間違えていたらアプリをクラッシュさせてくれ」と言う意味でわざとやっています。一度実行すれば確実に検出できるような場所では、このようにわざとクラッシュしてしまう書き方をする場合があります。

* * *

さて、上記のコードがクラッシュしないような設定ですが、`UITableViewController`を使うなら、storyboard上で設定した方が楽かもしれませんが、ここではコードで設定する方法を書いておきます。

[code]

        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.
            self.tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
            //...
        }
    
[/code]

最初のコードで`withIdentifier:`に`"CustomCell"`と言う文字列を指定していますが、その文字列は`CustomCell`と言うクラスを表しているんだよ、と言うのを登録することになります。

(本当は`"CustomCell"`と言う文字列は定数宣言しておいた方が良いところです。)

* * *

実際に上記の修正をやってみて、どのように表示されるか試してみて下さい。うまくいかない点やよくわからない点があれば、またコメントなどでお知らせください。


CC BY-SA 4.0
2020-06-30T09:15:11.043
68143
2020-06-30T09:15:11.043
13972
68141
answer


`viewDidLoad`等、`UITableView`のインスタンスをメンバーに持つクラスで、`UITableView`を使い始める前に対象の`UITableView`のインスタンスに  
`register(_:forCellReuseIdentifier:)`か、`register(_ nib: UINib?,
forCellReuseIdentifier identifier:
String)`で、この`identifier`にはこのカスタムセル（のクラス）を使ってねと登録する必要があります。

ただし、上のソースで

[code]

    let cell = UITableViewCell()
    
[/code]

と毎回新規に`cell`を作成していますが、  
`dequeueReusableCell(withIdentifier identifier: String) ->
UITableViewCell?`や、`dequeueReusableCell(withIdentifier identifier: String, for
indexPath: IndexPath) ->
UITableViewCell`で、再利用可能なセルがないか確認した方がセルを毎回新規に作るよりパフォーマンスが向上すると思います。


CC BY-SA 4.0
2020-06-30T09:17:40.057
68144
2020-06-30T09:17:40.057
14745
68141
answer