gpt4 book ai didi

swift - 将 SwiftUI View 添加到 UITableViewCell contentView

转载 作者:行者123 更新时间:2023-12-01 22:40:38 24 4
gpt4 key购买 nike

我目前正在尝试在 UIViewControllerRepresentable 中实现 UITableViewController,其中单元格的内容又是 SwiftUI View 。我无法使用 SwiftUI 列表,因为我想稍后添加 UISearchController。
因为我希望能够将自定义 SwiftUI View 作为每个单元格的内容,所以如果单元格内没有 SwiftUI View ,我不可能做到这一点。
我当前的代码不起作用,如下所示:

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
}
}
}

当我运行此命令时,例如使用此预览设置:

#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

我只看到一个 TableView,其中有 4 个显然是空的单元格。在 View 层次结构调试器中,我可以看到,每个单元格确实都有 NavigationLink,其中的文本作为 subview ,只是不可见。因此我认为,这与将 UIHostingController 添加为 UITableViewController 的子级有关,但我只是不知道应该在哪里添加它。
目前有办法做到这一点吗?

最佳答案

我在尝试做同样的事情时发现了这一点,这对我有用。

对我来说,这是子类化和隐藏导航栏所必需的

import UIKit
import SwiftUI
/// SwiftUI UIHostingController adds a navbar for some reason so we must disable it
class ControlledNavigationHostingController<Content>: UIHostingController<AnyView> where Content: View {

public init(rootView: Content) {
super.init(rootView: AnyView(rootView.navigationBarHidden(true)))
}

@objc dynamic required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = true
}
}

这是要使用的主要对象

/// This UITableViewCell  wrapper allows you to have a SwiftUI View in your UITableView
class HostingTableViewCell<Content: View>: UITableViewCell {
/// This holds the SwiftUI View being displayed in this UITableViewCell wrapper
private weak var swiftUIContainer: ControlledNavigationHostingController<Content>?
/// Put the SwiftUI View into the contentView of the UITableViewCell, or recycle an exisiting instance and add the new SwiftUIView
///
/// - Parameter view: The SwiftUI View to be used as a UITableViewCell
/// - Parameter parent: The nearest UIViewController to be parent of the UIHostController displaying the SwiftUI View
/// - Warning: May be unpredictable on the Simulator
func host(_ view: Content, parent: UIViewController) {
if let container = swiftUIContainer {
// Recycle this view
container.rootView = AnyView(view)
container.view.layoutIfNeeded()

} else {
// Create a new UIHostController to display a SwiftUI View
let swiftUICellViewController = ControlledNavigationHostingController(rootView: view)
swiftUIContainer = swiftUICellViewController

// Setup the View as the contentView of the UITableViewCell
swiftUICellViewController.view.backgroundColor = .clear
// Add the View to the hierarchy to be displayed
parent.addChild(swiftUICellViewController)
contentView.addSubview(swiftUICellViewController.view)
swiftUICellViewController.view.translatesAutoresizingMaskIntoConstraints = false
if let view = swiftUICellViewController.view {
contentView.addConstraint(NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1.0, constant: 0.0))
contentView.addConstraint(NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1.0, constant: 0.0))
contentView.addConstraint(NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1.0, constant: 0.0))
contentView.addConstraint(NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1.0, constant: 0.0))
}

swiftUICellViewController.didMove(toParent: parent)
swiftUICellViewController.view.layoutIfNeeded()
}
}
}

像这样注册:

tableView.register(HostingTableViewCell<YourSwiftUIView>.self, forCellReuseIdentifier: "WhateverIDYouWant")

然后像这样使用:

guard let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID", for: indexPath) as? HostingTableViewCell<SomeSwiftUIView> else {
print("Error: Could Not Dequeue HostingTableViewCell<SomeSwiftUIView>")
return UITableViewCell()
}
cell.host(SomeSwiftUIView(), parent: self)

关于swift - 将 SwiftUI View 添加到 UITableViewCell contentView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57627641/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com