Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning CGFloat.leastNormalMagnitude for UITableView section header causes crash

I made an app for iOS 8 which uses grouped UITableView for one of its page. There are multiple sections in it that uses CGFloat.leastNormalMagnitude (or CGFloat.min in Swift 2 and below) for section header and footer height to remove the "default" space. Everything went well until the app run in iOS 9 and 10, where it crashes with this error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'section header height must not be negative - provided height for section 0 is -0.00000'

Somehow, any value under 1 (except the rounded 0) is treated as a negative - and using 1 as return value will make the header / footer space appears again.

Is there any workaround to fix this?

Thanks in advance.

like image 324
edopelawi Avatar asked Feb 15 '17 10:02

edopelawi


2 Answers

I have tried several values for the tableView(_:heightForHeaderInSection:), and found out that:

  • leastNormalMagnitude and leastNonzeroMagnitude will be treated as minus (hence the crash).
  • Zero will make the TableView return the default height as header / footer.
  • Anything between zero and one will be treated as a minus.
  • One will make the TableView return the default height.
  • Anything more than one (e.g 1.1) will set the header / footer to the actual height.

I ended up using 1.1 for solving my problem.

Hope this will help someone out there!

like image 198
edopelawi Avatar answered Nov 08 '22 00:11

edopelawi


We've experienced the same running on iOS 9 using Swift 5 running Xcode 10.2. It turns out if you return CGFloat.leastNormalMagnitude or CGFloat.leastNonzeroMagnitude in estimatedHeightForHeaderInSection / estimatedHeightForFooterInSection, it will crash on iOS 9 devices.

You can still return leastNormalMagnitude or leastNonzeroMagnitude in heightForHeaderInSection / heightForFooterInSection.

As edopelawi pointed out above, any value less than 1 will be treated as negative, and 1 will be treated as the default grouped section header/footer height. We ended up returning 1.000001 as the estimated height if devices are running iOS 10 or below:


func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
    if #available(iOS 11.0, *) {
        return self.tableView(tableView, heightForHeaderInSection: section)
    } else {
        return max(1.000001, self.tableView(tableView, heightForHeaderInSection: section))
    }
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return 10
    }
    return CGFloat.leastNonzeroMagnitude
}
like image 41
Casey Avatar answered Nov 07 '22 23:11

Casey