自定义 Table 查看 outlets throwing nil

Custom Table View outlets throwing nil

我正在尝试使用遵循此 tutorial 的 VIPER 模式来实现一个简单的 iOS 应用程序。该应用程序是一个简单的 table 视图,它显示来自 json req

的数据

我已经创建了 table 视图,并且可以使用默认 cell.textLabel 成功地显示来自我的对象的数据。然而,我正在尝试创建一个自定义 table 视图单元,因此创建了笔尖和 class。我已将所有插座正确连接到笔尖的 class,此 class 的代码如下:

class CustomTableViewCell: UITableViewCell {
    
    static let identifier = "CustomTableView"
    
    static func nib() -> UINib {
        return UINib(nibName: "CustomTableViewCell", bundle: nil)
    }

    @IBOutlet var level: UILabel!
    @IBOutlet var levelNumber: UILabel!
    @IBOutlet var progress: UIProgressView!
    @IBOutlet var leftProgress: UILabel!
    @IBOutlet var rightProgress: UILabel!
    
    public func configure(levelString: String, levelNum: String, prog: Float, left: String, right: String) {
        level.text = levelString
        levelNumber.text = levelNum
        progress.setProgress(prog, animated: true)
        leftProgress.text = left
        rightProgress.text = right
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

问题 是,当我 运行 应用程序时,这些出口出现错误:Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value on level.text inside the configure function。在我看来,我可以通过这样做来抑制这个错误: table.register(CustomTableViewCell.nib(), forCellReuseIdentifier: CustomTableViewCell.identifier) 然而,这只是显示一个空的 table 视图,没有自定义行或任何数据。如果我这样做 table.register(CustomTableViewCell.self, forCellReuseIdentifier: CustomTableViewCell.identifier) 那么这会崩溃。我应该以什么方式进行操作以及如何让数据显示在 table 视图中?相关代码添加如下:

let tableView: UITableView = {
    let table = UITableView()
    table.register(CustomTableViewCell.nib(), forCellReuseIdentifier: CustomTableViewCell.identifier)
    table.isHidden = true
    return table
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(tableView)
    tableView.delegate = self
    tableView.dataSource = self
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    tableView.frame = view.bounds
    label.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
    label.center = view.center
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return achievements.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier, for: indexPath) as! CustomTableViewCell
    cell.configure(levelString: "Level",
                     levelNum: achievements[indexPath.row].level,
                     prog: Float(achievements[indexPath.row].progress/achievements[indexPath.row].total),
                     left: String(achievements[indexPath.row].progress),
                     right: String(achievements[indexPath.row].total))
    return cell
}

插座设置:

文件所有者:

我很欣赏这可能不是每个人的正确答案,但这对我有用。我一直在努力调试它,为了节省时间,我得出结论,以编程方式创建所有内容会更容易。有很多教程,但我采用了以下结构: 用于为组件设置约束和添加子视图的 Stevia 库

import Stevia
import UIKit

class CustomTableViewCell: UITableViewCell {
    
    static let identifier = "CustomTableViewCell"
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupFieldsAndConstraints()
    }
    
    func setupFieldsAndConstraints() {
        subviews {
            customLabel
        }
        setupCustomLabel()
    }
    
    var customLabel: UILabel = {
        let level = UILabel()
        return level
    }()
    
    func setupCustomLabel() {
        customLabel.style { l in
            l.textAlignment = .left
            l.textColor = .white
            l.Top == 50
            l.Left == 20
        }
    }
    
    func setValues(object: Object) {
        label.text = object.name
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

并且在您的视图中引用了它,因为它通常是这样的。我选择将我的添加到封装任何 table 配置的函数中,然后调用 viewDidLoad:

tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: CustomTableViewCell.identifier)

然后 cellForRowAt:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier) as! CustomTableViewCell
    cell.setValues(object: Object[indexPath.row])
    return cell
}