I've got a basic UITableView
with some cells. I'm using a SwiftUI View
as content for both my cells and section headers. Strangely, only the section header that appears to touch the bottom of the screen on an iPhone XS Max seems to get a rawSafeAreaInset
of 16pts (checked Debug View Hierarchy). My cells are working as expected.
To see what's going one, I have added a dummy blue SwiftUI rectangle to the contentView
, and then placed a red UIView on top, both views set to the same constraints. The UITableView
has been set to use automatic dimensions for headers and cells.
public class SectionHeader: UITableViewHeaderFooterView {
public static let reusableIdentifier = "Section"
private var innerHostedViewController: UIHostingController<AnyView>!
public override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
setupHeader()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupHeader() {
self.backgroundView = UIView()
self.backgroundView?.backgroundColor = UIColor.green.withAlphaComponent(0.2)
innerHostedViewController = UIHostingController(rootView: AnyView(Rectangle().fill(Color.blue).frame(height: 48)))
innerHostedViewController.view.translatesAutoresizingMaskIntoConstraints = false
innerHostedViewController.view.frame = self.contentView.bounds
contentView.addSubview(innerHostedViewController.view)
innerHostedViewController.view.backgroundColor = .clear
let vv = UIView()
vv.translatesAutoresizingMaskIntoConstraints = false
vv.backgroundColor = .red
contentView.addSubview(vv)
NSLayoutConstraint.activate([
vv.topAnchor.constraint(equalTo: self.contentView.topAnchor),
vv.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
vv.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
vv.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor),
innerHostedViewController.view.topAnchor.constraint(equalTo: self.contentView.topAnchor),
innerHostedViewController.view.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
innerHostedViewController.view.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
innerHostedViewController.view.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor),
])
}
}
As you can see in the image below, the red overlay is visible for the top two headers (with empty cells for demonstration), but the last one on the screen has its blue SwiftUI rectangle shifted upwards!
This SwiftUI view seems to be getting some safeAreaInset somehow, and there seems to be no way to turn this off. The inset also does not go away if you scroll up. It stays there forever. I tried turning off safe area insets for the SwiftUI view, but that doesn't help either:
innerHostedViewController = UIHostingController(rootView: AnyView(Rectangle().fill(Color.blue).frame(height: 48).edgesIgnoringSafeArea(.all)))
How do I get rid of this inset? As I mentioned - it's only happening to UITableViewHeaderFooterView
s and not UITableViewCell
s.
The debug view hierarchy reveals a bogus bottom padding modifier based on the safe area insets:
disableSafeArea: Bool
on UIHostingView, but since it's a private class we can't set it :( I assume it's what they are using in the implementation of List etc. – Wolfe