如何通过代码实现带自定义UITableViewCell子类的UITableView?
纯代码实现自定义UITableViewCell(带图片+标签)并复用的完整方案
没问题,我来给你一步步拆解纯代码实现自定义UITableViewCell并复用的方案,完全贴合你的需求:
1. 先创建自定义UITableViewCell子类
我们直接在代码里定义带图片和标签的cell,所有子视图的创建、布局都写在这个类里,不需要依赖Storyboard原型。
import UIKit class MyTableViewCell: UITableViewCell { // 自定义的图片视图 let iconImageView: UIImageView = { let imageView = UIImageView() imageView.contentMode = .scaleAspectFit imageView.clipsToBounds = true imageView.translatesAutoresizingMaskIntoConstraints = false // 关闭自动转换约束,开启AutoLayout return imageView }() // 自定义的文本标签 let titleLabel: UILabel = { let label = UILabel() label.font = UIFont.systemFont(ofSize: 16) label.translatesAutoresizingMaskIntoConstraints = false return label }() // 初始化方法——注册cell时,tableView会自动调用这个方法创建cell实例 override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupSubviews() // 初始化时就布局子视图 } // 纯代码实现不需要实现这个方法,直接抛错即可 required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 封装子视图布局逻辑 private func setupSubviews() { // *注意:必须把自定义子视图添加到cell的contentView,而不是cell本身* // 因为contentView是cell负责显示内容的区域,不受选中、高亮等状态的frame影响 contentView.addSubview(iconImageView) contentView.addSubview(titleLabel) // 用AutoLayout设置约束,确保在不同屏幕上都能正确布局 NSLayoutConstraint.activate([ // 图片:左边距16,垂直居中,宽高40 iconImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), iconImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), iconImageView.widthAnchor.constraint(equalToConstant: 40), iconImageView.heightAnchor.constraint(equalToConstant: 40), // 标签:左边距图片12,右边距16,垂直居中,高度至少20(避免文字被截断) titleLabel.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: 12), titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16), titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), titleLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 20) ]) } // 封装数据配置方法,让控制器代码更简洁 func configure(with icon: UIImage?, title: String) { iconImageView.image = icon titleLabel.text = title } }
2. 在ViewController中注册并复用Cell
接下来在控制器里注册这个自定义cell,然后通过dequeueReusableCell()实现复用,完全符合你“一次性加载+复用”的需求:
import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let tableView = UITableView() // 模拟数据源,你可以替换成自己的业务数据 let dataSource: [(icon: UIImage?, title: String)] = [ (UIImage(systemName: "star.fill"), "我的收藏"), (UIImage(systemName: "message.fill"), "消息通知"), (UIImage(systemName: "person.fill"), "个人中心") ] override func viewDidLoad() { super.viewDidLoad() setupTableView() } private func setupTableView() { // 设置tableView的frame并添加到当前视图 tableView.frame = view.bounds tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(tableView) // 关键步骤:注册自定义cell类,告诉tableView需要创建哪个类的cell实例 tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "MyCell") // 设置数据源和代理 tableView.dataSource = self tableView.delegate = self // 设置cell高度:这里用自动高度,也可以设固定值比如60 tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 60 } // MARK: - UITableViewDataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataSource.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 复用cell:从复用队列中取出可用的cell,没有的话会自动创建(因为我们注册了类) let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyTableViewCell // 给cell配置对应的数据 let item = dataSource[indexPath.row] cell.configure(with: item.icon, title: item.title) return cell } }
关于你的疑问解答
你提到“注册后无需使用(原文缺失),但不使用该方式时,如何为UITableViewCell的视图添加子视图?”——其实注册cell之后,tableView在需要新cell时,会自动调用我们自定义cell的init(style:reuseIdentifier:)方法创建实例,所以我们把添加子视图、布局约束的逻辑放在这个初始化方法里就完全可以了,不需要依赖Storyboard的原型cell,纯代码就能搞定。
这样既满足了注册cell实现复用的需求,又能完全自定义cell的内容布局。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

