纯代码实现UIKit中UITableView不显示问题求助
解决UITableView不显示且cellForRowAt未执行的问题
问题现象
- 纯代码开发UIKit应用,将其他视图控制器中正常运行的UITableView代码复制到
CreateWorkoutVC后,无编译报错但表格完全不显示,调试视图层级中找不到该UITableView。 - 调试时反复出现日志:
[API] Failed to get renderer info (client=0x82b3d507) [0x5 (os/kern) failure]。 numberOfRowsInSection中的print语句正常执行,但cellForRowAt中的print语句从未触发。
核心原因
- 约束不完整:UITableView仅配置了top、leading、trailing约束,缺少bottom约束或高度约束,导致表格视图高度为0,没有可渲染的区域,因此系统不会调用
cellForRowAt方法。 - UI配置时机错误:在
init方法中调用configure时,视图控制器的view尚未完成初始化,此时view.frame为无效的CGRect.zero,虽然后续启用了自动布局,但提前操作视图存在潜在风险。
修复方案
- 补充完整约束:为UITableView添加bottom约束,使其与父视图底部对齐(或根据需求设置固定高度),确保表格有明确的尺寸范围。
- 调整UI配置时机:将
configure方法的调用从init移至viewDidLoad,确保视图初始化完成后再配置表格组件。 - 优化cell内组件添加方式:将UILabel添加到cell的
contentView中,避免cell复用时重复添加子视图;若需求复杂,建议自定义UITableViewCell。
修正后的完整代码
CreateWorkoutVC
class CreateWorkoutVC: UIViewController, UITableViewDataSource, UITableViewDelegate { var exerciseListing: UITableView! var workoutTemplate: WorkoutTemplate! init(workoutTemplate: WorkoutTemplate) { super.init(nibName: nil, bundle: nil) self.workoutTemplate = workoutTemplate } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground configure() // 移至viewDidLoad中调用 } private func configure() { let padding: CGFloat = 20 exerciseListing = UITableView(frame: .zero) // 直接用.zero替代view.frame,因为后续会用自动布局 view.addSubview(exerciseListing) exerciseListing.register(UITableViewCell.self, forCellReuseIdentifier: "exercise") exerciseListing.rowHeight = 50 exerciseListing.dataSource = self exerciseListing.delegate = self exerciseListing.translatesAutoresizingMaskIntoConstraints = false // 补充bottom约束,确保表格有高度 NSLayoutConstraint.activate([ exerciseListing.topAnchor.constraint(equalTo: view.topAnchor, constant: padding), exerciseListing.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: padding), exerciseListing.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -padding), exerciseListing.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -padding) // 新增bottom约束 ]) } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { print("In numberOfRowsInSection: \(workoutTemplate.exerciseSets.count)") return workoutTemplate.exerciseSets.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "exercise", for: indexPath) // 先清空contentView的子视图,避免复用重复添加 cell.contentView.subviews.forEach { $0.removeFromSuperview() } let cellLabel = getCellLabel(withText: workoutTemplate.exerciseSets[indexPath.row].exercise.exerciseName) print(workoutTemplate.exerciseSets[indexPath.row].exercise.exerciseName) cell.contentView.addSubview(cellLabel) // 添加到contentView let padding: CGFloat = 8 NSLayoutConstraint.activate([ cellLabel.centerYAnchor.constraint(equalTo: cell.contentView.centerYAnchor), cellLabel.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: padding), cellLabel.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: -padding), cellLabel.heightAnchor.constraint(equalTo: cell.contentView.heightAnchor) ]) cell.backgroundColor = .secondarySystemBackground return cell } func getCellLabel(withText labelText: String) -> UILabel { let cellLabel = UILabel(frame: .zero) cellLabel.text = labelText cellLabel.textColor = .label cellLabel.adjustsFontSizeToFitWidth = true cellLabel.minimumScaleFactor = 0.90 cellLabel.lineBreakMode = .byTruncatingTail cellLabel.translatesAutoresizingMaskIntoConstraints = false cellLabel.textAlignment = .left cellLabel.font = UIFont.systemFont(ofSize: 16, weight: .bold) return cellLabel } }
数据结构(无需修改)
struct WorkoutTemplate { let workoutName: String var exerciseSets: [ExerciseSet] mutating func addExerciseSet(exerciseSet: ExerciseSet) { exerciseSets.append(exerciseSet) } static let exampleWorkouts = [WorkoutTemplate(workoutName: "Upper Body 1", exerciseSets: [ExerciseSet(exercise: Exercise(exerciseId: UUID(), exerciseName: "Bench Press"), sets: 3, targetReps: 8, targetRPE: 8, restPeriod: 2), ExerciseSet(exercise: Exercise(exerciseId: UUID(), exerciseName: "T-Bar Row"), sets: 3, targetReps: 8, targetRPE: 8, restPeriod: 3)]), WorkoutTemplate(workoutName: "Lower Body 1", exerciseSets: [ExerciseSet(exercise: Exercise(exerciseId: UUID(), exerciseName: "Hack Squats"), sets: 3, targetReps: 8, targetRPE: 8, restPeriod: 2), ExerciseSet(exercise: Exercise(exerciseId: UUID(), exerciseName: "Leg Ext"), sets: 3, targetReps: 8, targetRPE: 8, restPeriod: 3)])] } struct ExerciseSet { let exercise: Exercise let sets: Int let targetReps: Int let targetRPE: Int let restPeriod: Int } struct Exercise { let exerciseId: UUID let exerciseName: String }
内容的提问来源于stack exchange,提问作者Legion
相关产品推荐
相关产品推荐

