Returning CGFloat.leastNormalMagnitude for UITableView section header causes crash
Asked Answered
P

5

10

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.

Protestantism answered 15/2, 2017 at 10:3 Comment(4)
So is CGFloat.leastNormalMagnitude treated as negative, or is any value under 1.0 treated as negative?Hydrokinetics
yes, and I don't know why :|Protestantism
Have you tried returning just 0? That works for meHolocaine
Returning 0 will make the space on the header / footer...Protestantism
P
24

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!

Protestantism answered 13/3, 2017 at 16:28 Comment(4)
I don't understand how you solved your issue by setting 1.1. If you set the height to 1.1, you still get non-zero space for your section header right ?Olfactory
@Olfactory yes, I ended up filling the 1.1 space with a view that uses same background color with the table view.Protestantism
This is just sad behaviour.Outrelief
@JakubTruhlář and undocumented, on top of that... but well, life goes on :)Protestantism
C
4

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
}
Crashing answered 24/4, 2019 at 8:47 Comment(0)
C
1

I have same issue if I set section header height with:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = CGFloat.leastNormalMagnitude

But if I set my Controller as delegate (UITableViewDelegate) for my table view and implement:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

then it works

Courbet answered 16/2, 2017 at 13:4 Comment(1)
Thank you for your response, but my issue was occurred with the UITableviewDelegate set, without setting the tableView's sectionHeaderHeight and estimatedSectionHeaderHeight manually :(Protestantism
K
0

Maybe CGFloat.leastNonzeroMagnitude is what you need!

Kelvin answered 23/2, 2017 at 5:24 Comment(1)
Thank you for your answer, but it still crashed with that value :(Protestantism
G
0

If you implement viewForHeader and viewForFooter you don't have to make any cheat.

I personally return 0.1f when I want to hide the header and/or the footer for example. This example will completely hide header and footer with no space to fill, from that you can add your custom logic.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 0.1f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 0.1f;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
     return nil;
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
    return nil;
}
Guarantor answered 4/11, 2019 at 21:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.