2

We do have a TableViewModel which is implementing the UITableViewDelegate and the UITableViewDataSource. It holds the sections and returns the right rows and elements of our UITableViews.

Now we want to have a custom table view section footer. Therefor we implement the optional public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? so that this returns a UIView from a xib file. This is all fine but it ends up in a wrong footer height. If we use func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? the footer is displayed correct and the height of the footer is set correct.

So we also have to implement the optional public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat or the optional public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat

  1. Question: How do i get the height of an UIView which this was instantiated? view.frame.bounds or view.frame.height is always 0.
  2. Question: What is the default value Apple uses for the footer and how does it calculate that? I recognised that if we return table.sectionFooterHeight for the default (not our custom footer view) the hight is correct.

TableViewModel:

class TableViewModel: NSObject, UITableViewDelegate, UITableViewDataSource {

    var sections: [TableViewSection] = []

    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sections[section].numberOfRowsInTableView(tableView)
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return sections[(indexPath as NSIndexPath).section].tableView(tableView, cellForRowAtIndexPath: indexPath)
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        sections[(indexPath as NSIndexPath).section].tableView(tableView, didSelectRowAtIndexPath: indexPath)
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section].headerText
    }

    func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
        sections[section].tableView(tableView, willDisplayHeaderView: view)
    }

    func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        return sections[section].footerText
    }

    func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
        sections[section].tableView(tableView, willDisplayFooterView: view)
    }

    func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
        return sections[(indexPath as NSIndexPath).section].tableView(tableView, cellContentsToCopyAtIndexPath: indexPath, withSender: nil) != nil
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        ??
    }

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return sections[section].footerView
    }

    func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
        ??
    }
}
bemeyer
  • 6,154
  • 4
  • 36
  • 86
  • did you try to save your height in a variable when you set titleForFooterInSection? Something like: footerHeight = sections[section].footerText.frame.bounds.height , where footerHeight is a variable in your controller and you can use it as a return value for 'heightForFooterInSection' – Eugen Dimboiu Nov 14 '16 at 14:32
  • Do your footers have a fixed height? Or is their height dynamic and set by AutoLayout? – paulvs Nov 14 '16 at 14:33
  • Yes but that would mean that i have to set the height when i create the footer. I cant know the height of it on every device (containing strings so dynamic height depending on the phone size) Somehow the interfacebuilder of apple does set the hight on the default views. – bemeyer Nov 14 '16 at 14:33

2 Answers2

2

I solved it by adding the following method:

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return sections[section].footerViewHeight ?? UITableViewAutomaticDimension
}

And returning the calculated height for the footer in section. It does resize properly and we are able to adjust it. As mentioned, returning the UITableViewAutomaticDimension requires:

// Returning this value from tableView:heightForHeaderInSection: or tableView:heightForFooterInSection: results in a height that fits the value returned from // tableView:titleForHeaderInSection: or tableView:titleForFooterInSection: if the title is not nil.
bemeyer
  • 6,154
  • 4
  • 36
  • 86
-1

If you are using auto layout you can still return UITableViewAutomaticDimension in heightForFooterInSection and the footer's height will be automatically calculated. As same with heightForRowAt , heightForFooterInSection must be used in combination with estimatedHeightForFooterInSection. A simple example would look like this:

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat {
    return 18 // or whatever value
}
unniverzal
  • 803
  • 10
  • 17
Zell B.
  • 10,266
  • 3
  • 40
  • 49
  • Thanks for the answer. I'll give it a try and see how it works. Wi give feedback. – bemeyer Nov 14 '16 at 14:51
  • `// Returning this value from tableView:heightForHeaderInSection: or tableView:heightForFooterInSection: results in a height that fits the value returned from // tableView:titleForHeaderInSection: or tableView:titleForFooterInSection: if the title is not nil.` – bemeyer Nov 17 '16 at 09:36
  • @BennX Where did you get this? In one of my projects this is working as expected – Zell B. Nov 17 '16 at 09:59
  • If you follow Xcode to the definition of `UITableViewAutomaticDimension` that is written there. – bemeyer Nov 17 '16 at 10:00
  • @BennX I can confirm for sure that `UITableViewAutomaticDimension` works with `heightForFooterInSection` if `titleForFooterInSection` returns nil and `estimatedHeightForFooterInSection ` is implemented. Also make sure that you have set all constrains correctly as described here : http://stackoverflow.com/a/30300870/1422333 – Zell B. Nov 17 '16 at 10:14