You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纯代码实现UIKit中UITableView不显示问题求助

解决UITableView不显示且cellForRowAt未执行的问题

问题现象

  • 纯代码开发UIKit应用,将其他视图控制器中正常运行的UITableView代码复制到CreateWorkoutVC后,无编译报错但表格完全不显示,调试视图层级中找不到该UITableView。
  • 调试时反复出现日志:[API] Failed to get renderer info (client=0x82b3d507) [0x5 (os/kern) failure]。
  • numberOfRowsInSection中的print语句正常执行,但cellForRowAt中的print语句从未触发。

核心原因

  1. 约束不完整:UITableView仅配置了top、leading、trailing约束,缺少bottom约束或高度约束,导致表格视图高度为0,没有可渲染的区域,因此系统不会调用cellForRowAt方法。
  2. UI配置时机错误:在init方法中调用configure时,视图控制器的view尚未完成初始化,此时view.frame为无效的CGRect.zero,虽然后续启用了自动布局,但提前操作视图存在潜在风险。

修复方案

  1. 补充完整约束:为UITableView添加bottom约束,使其与父视图底部对齐(或根据需求设置固定高度),确保表格有明确的尺寸范围。
  2. 调整UI配置时机:将configure方法的调用从init移至viewDidLoad,确保视图初始化完成后再配置表格组件。
  3. 优化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 16:52:50