サンプルプロジェクト & 問題点
カスタムセルを使ってTableViewにUIImageとUILabelを表示させる
ビルドも正常に出来ていて問題がないように見えますが、一点修正すべき部分があります。
それが、
CustomTableViewCell内のUIパーツをViewController.swift内で処理している
という部分です。
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruitsDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as? CustomTableViewCell else {
return UITableViewCell()
}
// CustomTableViewCellのUIパーツを外部で処理しまっている -- ここから
cell.fruitsImageView.image = UIImage(named: fruitsDataArray[indexPath.row].fruitsImageName)
cell.fruitsNameLabel.text = fruitsDataArray[indexPath.row].fruitsName
// CustomTableViewCellのUIパーツを外部で処理しまっている -- ここまで
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.view.frame.height / 8.5
}
}
これはViewのライフサイクル上望ましくなく、基本的にはそのUIパーツを紐づけているファイル内で処理をさせるようにしなければなりません。
修正方法
CustomCell内の関数に引数を持たせて、そこにIndexPath.row番目の情報を渡してあげるという形にしてあげましょう
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruitsDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as? CustomTableViewCell else {
return UITableViewCell()
}
// CustomCell内の関数に引数を持たせて、そこにIndexPath.row番目の情報を渡す
cell.configureCustomCell(fruitsImageName: fruitsDataArray[indexPath.row].fruitsImageName, fruitsName: fruitsDataArray[indexPath.row].fruitsName)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.view.frame.height / 8.5
}
import UIKit
class CustomTableViewCell: UITableViewCell {
@IBOutlet private weak var fruitsImageView: UIImageView!
@IBOutlet private weak var fruitsNameLabel: UILabel!
func configureCustomCell(fruitsImageName: String, fruitsName: String) {
fruitsImageView.image = UIImage(named: fruitsImageName)
fruitsNameLabel.text = fruitsImageName
}
}
import UIKit
class ViewController: UIViewController {
@IBOutlet private weak var tableView: UITableView!
private var fruitsDataArray: [(fruitsImageName: String, fruitsName: String)] = [
("Banana", "バナナ"),
("Apple", "リンゴ"),
("Grape", "ブドウ"),
("Strawberry", "イチゴ"),
("Mango", "マンゴー"),
("Orange", "オレンジ"),
("Pineapple", "パイナップル")
]
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
}
private func configureTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruitsDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as? CustomTableViewCell else {
return UITableViewCell()
}
// CustomCell内の関数に引数を持たせて、そこにIndexPath.row番目の情報を渡す
cell.configureCustomCell(fruitsImageName: fruitsDataArray[indexPath.row].fruitsImageName, fruitsName: fruitsDataArray[indexPath.row].fruitsName)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.view.frame.height / 8.5
}
}