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?
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")
}
}