I'm working on a legacy app and trying to embed a swiftUI view inside a UIKit UITableView. The SwiftUI view is a LazyHGrid with a number of items based on a user's number of accounts. The idea is to display the first 1-3 items (if there are any), and a "More" button, which, when tapped, displays the rest of the items.
The SwiftUI piece is working correctly, and initially the tableView displays it correctly, like so: three tiles working correctly. However, when I tap the "More" button, the other items pop in, but the row height in the table doesn't adjust, so they just overlap the other content in the table, like so: tiles overlapping other content.
Here's the host function that controls the swiftUI view:
func host(_ view: Content, parent: UIViewController) {
hostingController.rootView = view
hostingController.view.invalidateIntrinsicContentSize()
let requiresControllerMove = hostingController.parent != parent
if requiresControllerMove {
// remove old parent if exists
removeHostingControllerFromParent()
parent.addChild(hostingController)
}
if !contentView.subviews.contains(hostingController.view) {
contentView.addSubview(hostingController.view)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
hostingController.view.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
hostingController.view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
hostingController.view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
hostingController.view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
}
if requiresControllerMove {
hostingController.didMove(toParent: parent)
}
}
I register the cell in the viewDidLoad in the UIKit controller:
self.tableView.register(SwiftUIHostTableViewCell<BillingTileGridView>.self, forCellReuseIdentifier: "BillingTileGridViewCell")
(This code was already present in the viewDidLoad):
self.tableView.estimatedRowHeight = 60
self.tableView.rowHeight = UITableView.automaticDimension
And then I create the cell like so in the tableView cellForRowAt function:
if let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseID, for: indexPath) as? SwiftUIHostTableViewCell<BillingTileGridView> {
let view = BillingTileGridView(viewModel: BillingTileGridViewModel(), adjustHeight: {
})
cell.host(view, parent: self)
return cell
}
I tried using a callback to re-load the table height for the button action, like this:
let view = BillingTileGridView(viewModel: BillingTileGridViewModel(), adjustHeight: {
tableView.beginUpdates()
tableView.endUpdates()
})
like I'd seen in questions like this one, Swift: How to reload row height in UITableViewCell without reloading data, but it didn't seem to do anything. Do I just need to calculate the height manually based on how many rows I have, and set the height explicitly to that?