Se me ocurrió una solución para solucionar este problema. Una advertencia, mientras soluciona el cambio en la tabla, introduce un retraso en la animación del título de la barra de navegación, por lo que está advertido.
Mientras tanto, puede usar TableViewController de UIKit hasta que Apple arregle el objeto Lista de SwiftUI.
En resumen, debe crear un TableViewController y envolverlo en UIViewControllerRepresentable para luego inyectarlo en su vista SwiftUI. La acción de navegación se realiza mejor a través del método delegado didSelectRowAt.
Actualización: parece que el problema se ha resuelto en el nuevo XCode 11.4 (sin embargo, ahora hay más problemas en el entorno del simulador)
Tengo un código completo aquí: https://gist.github.com/Rep0se/97d7a97cfd05f42aa597904e6a2cfd3d
//
// UIKitSwiftUITableView.swift
// Table Test
//
// Created on 2020-02-19.
// Note: While this solution fixes Table shifting bug, it introduces Navigation Bar Title bug for a Large Title. Beware.
// LBTATools can be downloaded using Swift Package Manager from: https://github.com/bhlvoong/LBTATools
//
import SwiftUI
import LBTATools
struct UIKitSwiftUITableView: View {
var body: some View {
NavigationView {
UIKitSwiftUIContainer()
}
}
}
struct Restaurante: Hashable {
let name: String
let image: String
}
struct UIKitSwiftUIContainer: View {
let restaurants = [
Restaurante(name: "Joe's Original", image: "house"),
Restaurante(name: "Pheasant Plucker", image: "house.fill"),
Restaurante(name: "Radius", image: "music.house"),
Restaurante(name: "The Ship", image: "music.house.fill")
]
var body: some View {
UIKitTableViewRepresentable(restaurants: restaurants)
.navigationBarTitle("Select a restaurant") // <- UI bug exests for Navigation Bar Title
.edgesIgnoringSafeArea(.all)
}
}
struct UIKitTableViewRepresentable: UIViewControllerRepresentable {
typealias UIViewControllerType = UIViewController
let restaurants: [Restaurante]
init(restaurants: [Restaurante]) {
self.restaurants = restaurants
}
func makeUIViewController(context: UIViewControllerRepresentableContext<UIKitTableViewRepresentable>) -> UIViewController {
UIKitComboTableViewController(restaurants: restaurants)
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<UIKitTableViewRepresentable>) {
}
}
class UIKitComboTableViewController: UITableViewController {
let reuseIdentifier = "reuseIdentifier"
var restaurants: [Restaurante]
init(restaurants: [Restaurante]) {
self.restaurants = restaurants
super.init(style: .insetGrouped)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(TableCell.self, forCellReuseIdentifier: reuseIdentifier)
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return restaurants.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as? TableCell {
cell.viewModel.name = restaurants[indexPath.row].name
cell.viewModel.image = restaurants[indexPath.row].image
cell.accessoryType = .disclosureIndicator
return cell
} else {
return UITableViewCell()
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let hostingController = UIHostingController(rootView: UIKitSwiftUIContainer())
show(hostingController, sender: self)
}
}
class TableCell: UITableViewCell {
let viewModel = RestaurantViewModel()
lazy var row = ListRowView(viewModel: viewModel)
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let hostingController = UIHostingController(rootView: row)
addSubview(hostingController.view)
hostingController.view.fillSuperview()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
struct ListRowView: View {
@ObservedObject var viewModel: RestaurantViewModel
var body: some View {
HStack{
Image("Avatar").renderingMode(.original).padding()
Text(viewModel.name)
.foregroundColor(.black)
Spacer()
}.frame(minHeight: 44)
}
}
class RestaurantViewModel: ObservableObject {
@Published var name = ""
@Published var image = ""
}
struct UIKitSwiftUITableView_Previews: PreviewProvider {
static var previews: some View {
UIKitSwiftUITableView()
}
}