Header 部分未在编程 UITableView 中显示

Section Header Not Showing in Programmatic UITableView

我正在尝试学习如何以编程方式创建不同的 UI 元素。我的 UITableView..

面临以下问题

我有 2 个 .swift 文件,一方面,我们有..

        struct SettingsView {

        let settingsCustomTable: UITableView = {

            let aTable = UITableView()
                aTable.sectionHeaderHeight = 42
                aTable.tableFooterView = UITableViewHeaderFooterView(frame:CGRect(x:0,
                                                                                  y:0,
                                                                                  width:aTable.frame.width,
                                                                                  height:0))

                aTable.register(SettingsCustomHeader.self, forHeaderFooterViewReuseIdentifier:"customHeader")
                aTable.register(SettingsCustomCell.self, forCellReuseIdentifier:"customCell")

            return aTable
        }()

    }


    ////////////////////////////////
    //  custom cell class below   //
    ////////////////////////////////

    private class SettingsCustomCell: UITableViewCell {

        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)

            contentView.addSubview(customCellLabel)
            customCellLabel.frame = CGRect(x:16,
                                           y:0,
                                           width: self.frame.width,
                                           height:self.frame.height)
        }

        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

        private let customCellLabel: UILabel = {

            let aLabel = UILabel()
                aLabel.text = "custom label"
                aLabel.textColor = appGreenColor(alphaIs: 1)

            return aLabel
        }()
    }


    //////////////////////////////////
    //  custom header class below   //
    //////////////////////////////////

    private class SettingsCustomHeader: UITableViewHeaderFooterView {

        override init(reuseIdentifier: String?) {
            super.init(reuseIdentifier: reuseIdentifier)

            contentView.addSubview(customHeaderLabel)
            customHeaderLabel.frame = CGRect(x:0,
                                           y:0,
                                           width: self.frame.width,
                                           height:self.frame.height)
        }

        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

        private let customHeaderLabel: UILabel = {

            let aLabel = UILabel()
            aLabel.text = "custom header"
            aLabel.textColor = UIColor.white
            aLabel.backgroundColor = UIColor.red

            return aLabel
        }()

    }

在另一个 .swift 文件中,我有如下控制器..

class SettingsVC: UIViewController, UITableViewDelegate, UITableViewDataSource {

    private let instanceOfSettingsView = SettingsView()

    override func loadView() {
        super.loadView()

        instanceOfSettingsView.settingsCustomTable.delegate = self
        instanceOfSettingsView.settingsCustomTable.dataSource = self

        view.addSubview(instanceOfSettingsView.settingsCustomTable)
        instanceOfSettingsView.settingsCustomTable.frame = CGRect(x: 0,
                                                                  y: 0,
                                                                  width: self.view.frame.width,
                                                                  height: self.view.frame.height)

    }

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

    func numberOfSections(in tableView: UITableView) -> Int {
        return 2
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath)
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        return tableView.dequeueReusableHeaderFooterView(withIdentifier: "customHeader")
    }

如您所见,我对单元格和 header 部分使用了完全相同的方法。但是由于某些奇怪的原因,我得到了以下输出 (请检查此 post 末尾的屏幕截图)..

你能告诉我我错过了什么吗..?我试图让我的视图与我的控制器分开放置,除了那一小部分之外,这是成功的。

感谢您的帮助。

向自定义 header 的初始化函数添加一行:

   override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)

        contentView.addSubview(customHeaderLabel)
        customHeaderLabel.frame = CGRect(x:0,
                                       y:0,
                                       width: self.frame.width,
                                       height:self.frame.height)

        // add this line
        print("w:", self.frame.width, "h:", self.frame.height)
    }

你会看到,此时,框架还没有设置好。您的调试控制台输出应该是:

w: 0.0 h: 0.0
w: 0.0 h: 0.0

如果您在 customHeaderLabel 上设置约束而不是设置其框架,您应该会看到标签。 (它也可以帮助设置背景颜色,这样你就可以看到什么是什么)。

所以,"fill out" 这个答案...

使用视觉格式语言:

override init(reuseIdentifier: String?) {
    super.init(reuseIdentifier: reuseIdentifier)

    contentView.addSubview(customHeaderLabel)

    customHeaderLabel.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[chl]|", options: [], metrics:[:], views:["chl":customHeaderLabel]))
    NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|[chl]|", options: [], metrics:[:], views:["chl":customHeaderLabel]))

}

或使用锚点和.constraint格式:

override init(reuseIdentifier: String?) {
    super.init(reuseIdentifier: reuseIdentifier)

    contentView.addSubview(customHeaderLabel)

    customHeaderLabel.translatesAutoresizingMaskIntoConstraints = false

    customHeaderLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0).isActive = true
    customHeaderLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0.0).isActive = true
    customHeaderLabel.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: 0.0).isActive = true
    customHeaderLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0.0).isActive = true

}