I am in the process of learning uikit and having trouble with tables and cells. I have a project currently with a table view, programmatic, no storyboard that is giving me a error when trying to dequeue the table cell.
Fatal Error: The table cell could not dequeue a CustomCell in ViewController
The app crashes at the cell creation in the tableView.
I have checked over the tableview and custom cell for any mismatch in spelling but it all seems to line up. I expect the table to show a few images in a dummy array of UIImages. Thanks for any help.
Custom Cell
class CustomCell: UITableViewCell {
static let identifier = "CustomCell"
private let myImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleToFill
iv.image = UIImage(systemName: "photo")
iv.tintColor = .label
return iv
}()
private let myLabel: UILabel = {
let label = UILabel()
label.textColor = .label
label.textAlignment = .left
label.font = .systemFont(ofSize: 24, weight: .medium)
label.text = "Error"
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func configure(with image: UIImage, and label: String) {
self.myImageView.image = image
self.myLabel.text = label
}
private func setupUI() {
self.contentView.addSubview(myImageView)
self.contentView.addSubview(myLabel)
myImageView.translatesAutoresizingMaskIntoConstraints = false
myLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// setup the image constraints
myImageView.topAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.topAnchor),
myImageView.bottomAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.bottomAnchor),
myImageView.leadingAnchor.constraint(equalTo: self.contentView.layoutMarginsGuide.leadingAnchor),
// myImageView.heightAnchor.constraint(equalToConstant: 90),
myImageView.widthAnchor.constraint(equalToConstant: 90),
// setup the label constraints
myLabel.leadingAnchor.constraint(equalTo: self.myImageView.trailingAnchor, constant: 16),
myLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -12),
myLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor),
myLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor)
])
}
}
Table viewcontroller
class ActivityVC: UIViewController {
var user: User!
let gear = UITableView()
private let images: [UIImage] = [
UIImage(named: "0")!,
UIImage(named: "1")!,
UIImage(named: "2")!,
]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
setupUI()
setupNavControl()
}
private let tableView: UITableView = {
let tableView = UITableView()
tableView.backgroundColor = .systemBackground
tableView.allowsSelection = false
tableView.separatorStyle = .singleLine
tableView.register(UITableViewCell.self, forCellReuseIdentifier: CustomCell.identifier)
return tableView
}()
private func setupUI() {
self.view.backgroundColor = .systemBackground
self.view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: self.view.topAnchor),
tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
])
}
extension ActivityVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.images.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: CustomCell.identifier, for: indexPath) as? CustomCell else {
fatalError("The table cell could not dequeue a CustomCell in ViewController")
}
let image = self.images[indexPath.row]
cell.configure(with: image, and: indexPath.row.description)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 112.5
}
}
The problem is with this line from ActivityVC
:
tableView.register(UITableViewCell.self, forCellReuseIdentifier: CustomCell.identifier)
You are registering the class UITableViewCell
, but you are using CustomCell
. Although CustomCell
comes from UITableViewCell
, the casting fails.
You can fix it by changing it to:
tableView.register(CustomCell.self, forCellReuseIdentifier: CustomCell.identifier)