Returning CGFloat.leastNormalMagnitude for UITableView section header causes crash

假如想象 提交于 2019-12-20 20:29:36

问题


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.


回答1:


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!




回答2:


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
}



回答3:


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




回答4:


Maybe CGFloat.leastNonzeroMagnitude is what you need!




回答5:


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;
}


来源:https://stackoverflow.com/questions/42246153/returning-cgfloat-leastnormalmagnitude-for-uitableview-section-header-causes-cra

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!