web-dev-qa-db-fra.com

Ajouter une vue SwiftUI à un contenu UITableViewCell

J'essaie actuellement d'implémenter un UITableViewController dans un UIViewControllerRepresentable, où le contenu des cellules est à nouveau des vues SwiftUI. Je ne peux pas utiliser une liste SwiftUI, car je souhaite ajouter un UISearchController plus tard.
Parce que je veux pouvoir, pour mettre une vue SwiftUI personnalisée comme contenu de chaque cellule, ce n'est pas possible pour moi, de le faire sans SwiftUI Views à l'intérieur des cellules.
Mon code actuel, qui ne fonctionne pas, ressemble à ceci:

class SearchableListCell: UITableViewCell {
    let contentController: UIViewController

    init(withContent content: UIViewController, reuseIdentifier: String) {
        self.contentController = content

        super.init(style: .default, reuseIdentifier: reuseIdentifier)

        self.addSubview(self.contentController.view)
        // Tried also
        // self.contentView.addSubview(self.contentController.view)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

struct SearchableList: UIViewControllerRepresentable {
    let data: [String]

    var viewBuilder: (String) -> ContentView

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIViewController(context: Context) -> UITableViewController {
        return context.coordinator.tableViewController
    }

    func updateUIViewController(_ tableViewController: UITableViewController, context: Context) {
    }

    class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {
        var parent: SearchableList

        let tableViewController = UITableViewController()

        init(_ searchableList: SearchableList) {
            self.parent = searchableList

            super.init()

            tableViewController.tableView.dataSource = self
            tableViewController.tableView.delegate = self
        }

        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return parent.data.count
        }

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let string = self.parent.data[indexPath.row]

            let view = parent.viewBuilder(string)

            let hostingController = UIHostingController(rootView: view)

            let cell = SearchableListCell(withContent: hostingController, reuseIdentifier: "cell")

            // Tried it with and without this line:
            tableViewController.addChild(hostingController)

            return cell
        }
    }
}

Lorsque je l'exécute, par exemple avec cette configuration d'aperçu:

#if DEBUG
struct SearchableList_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            SearchableList(data: ["Berlin", "Dresden", "Leipzig", "Hamburg"]) { string in
                NavigationLink(destination: Text(string)) { Text(string) }
            }
            .navigationBarTitle("Cities")
        }
    }
}
#endif

Je vois juste une TableView avec 4 cellules apparemment vides. Dans le débogueur de hiérarchie de vues, je peux cependant voir que chaque cellule a en effet le lien de navigation avec du texte en tant que sous-vue, il n'est tout simplement pas visible. Par conséquent, je pense que cela a à voir avec l'ajout de l'UIHostingController en tant qu'enfant de l'UITableViewController, mais je ne sais tout simplement pas où je dois l'ajouter autrement.
Existe-t-il un moyen de le faire pour le moment?

5
Josef Zoller

Pour résoudre le problème de visibilité des cellules, modifiez la propriété UIHostingController qui transforme la propriété AutoresizingMaskIntoConstraints en false
, puis définissez son cadre de vue égal aux limites du contenu de la cellule ou vous pouvez utiliser NSLayoutConstraint,
vérifier ci-dessous

class SearchableListCell: UITableViewCell {
    let contentController: UIViewController

    init(withContent content: UIViewController, reuseIdentifier: String) {
        self.contentController = content

        super.init(style: .default, reuseIdentifier: reuseIdentifier)


        contentController.view.translatesAutoresizingMaskIntoConstraints = false
        contentController.view.frame = self.contentView.bounds

        self.contentView.addSubview(self.contentController.view)

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
1
ozmpai