UIView 作为 UITableView 的 header

UIView as a header for UITableView

我正在通过 "iOS Programming: The Big Nerd Ranch Guide (6th Edition)" 书学习 iOS 在 swift 中的编程,但它似乎有点过时了。我在故事板中向 UIViewTable 添加 header 时遇到问题。 在书中,它建议在原型单元格顶部添加一个 UIView,在其中放置带有约束的按钮,仅此而已,但就我而言,这是行不通的。按钮不会出现:( 所以,它看起来像这样:

你能帮我看看这个例子吗?

我的ItemsViewController.swift:

import UIKit

class ItemsViewController: UITableViewController {

    var itemStore: ItemStore!

    @IBAction func addNewItem(_ sender: UIButton) {

    }

    @IBAction func toggleEditingMode(_ sender: UIButton) {

        if isEditing {
            sender.setTitle("Edit", for: .normal)
            setEditing(false, animated: true)
        } else {
            sender.setTitle("Done", for: .normal)
            setEditing(true, animated: true)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")
    }

    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return itemStore.allItems.count + 1
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)

        if itemStore.allItems.count == indexPath.row {

            cell.textLabel?.text = "No more items"
        } else {

            let item = itemStore.allItems[indexPath.row]
            cell.textLabel?.text = item.name
            cell.detailTextLabel?.text = "$\(item.valueInDollars)"
        }

        return cell
    }
}

UPD:我已经通过 tableView(_:viewForHeaderInSection:) 以编程方式完成了该操作,但这并不方便。 有什么方法可以用storyboard的方式达到同样的效果吗?

可能与headerViewSize尺码有关。请尝试以下操作。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    guard let tableHeaderView = tableView.tableHeaderView else { return }
    let size = tableHeaderView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    if tableHeaderView.frame.size.height != size.height {
        tableHeaderView.frame.size.height = size.height
    }
    tableView.tableHeaderView = tableHeaderView
}

我找到了万恶之源。如果您像这样设置 ItemStore:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    guard let _ = (scene as? UIWindowScene) else { return }

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.windowScene = (scene as! UIWindowScene)
    window?.rootViewController = ItemsViewController()
    window?.makeKeyAndVisible()

    // Create an ItemStore
    let itemStore = ItemStore()

    // Access the ItemsViewController and set its item store
    let itemsController = window!.rootViewController as! ItemsViewController
    itemsController.itemStore = itemStore
}

不要那样做。对我来说是这样的:

override func viewDidLoad() {
    super.viewDidLoad()

    itemStore = ItemStore()

    tableView.rowHeight = UITableView.automaticDimension
    tableView.estimatedRowHeight = 65
}

这本书似乎已经过时了。