带有 UIViewRepresantable 的 UITableView 的某些单元格定位错误
Some cells of UITableView with UIViewRepresantable are positioned wrong
我正在尝试将 UITableView 与 UIViewRepresantable 一起使用,它有点管用,但不是真的。有些行放置在错误的位置,要么与其他行重叠,要么添加了额外的填充。此外,即使我设置了 automaticDimension,它似乎也不会使行高适应行的内容。
这是演示:
代码如下:
import SwiftUI
struct ContentView: View {
@State var rows : [String] = []
var listData = ListData()
var body: some View {
VStack {
Button(action: {
self.getDataFromTheServer()
}) {
Text("Get 100 entries from the server")
}
UIList(rows: $rows)
}
}
func getDataFromTheServer() {
for _ in 1...100 {
self.rows.append(self.listData.data)
self.listData.data.append("a")
}
}
}
class ListData {
var data: String = ""
}
class HostingCell: UITableViewCell {
var host: UIHostingController<AnyView>?
}
struct UIList: UIViewRepresentable {
@Binding var rows: [String]
func makeUIView(context: Context) -> UITableView {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.dataSource = context.coordinator
tableView.delegate = context.coordinator
tableView.register(HostingCell.self, forCellReuseIdentifier: "Cell")
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
return tableView
}
func updateUIView(_ uiView: UITableView, context: Context) {
DispatchQueue.main.async {
uiView.reloadData()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(rows: $rows)
}
class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {
@Binding var rows: [String]
init(rows: Binding<[String]>) {
self._rows = rows
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.rows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! HostingCell
let view = Text(rows[indexPath.row])
.background(Color.blue)
.lineLimit(nil)
// create & setup hosting controller only once
if tableViewCell.host == nil {
let hostingController = UIHostingController(rootView: AnyView(view))
tableViewCell.host = hostingController
let tableCellViewContent = hostingController.view!
tableCellViewContent.translatesAutoresizingMaskIntoConstraints = false
tableViewCell.contentView.addSubview(tableCellViewContent)
tableCellViewContent.topAnchor.constraint(equalTo: tableViewCell.contentView.topAnchor).isActive = true
tableCellViewContent.leftAnchor.constraint(equalTo: tableViewCell.contentView.leftAnchor).isActive = true
tableCellViewContent.bottomAnchor.constraint(equalTo: tableViewCell.contentView.bottomAnchor).isActive = true
tableCellViewContent.rightAnchor.constraint(equalTo: tableViewCell.contentView.rightAnchor).isActive = true
} else {
// reused cell, so just set other SwiftUI root view
tableViewCell.host?.rootView = AnyView(view)
}
tableViewCell.setNeedsLayout()
return tableViewCell
}
}
}
UIHostingControllers 不能很好地调整自己的大小,我怀疑这是破坏自动布局的原因。尝试在设置控制器的 rootView 后添加:
hostingController.preferredContentSize = hostingController.sizeThatFits( )
就是说,您可能想完全避免使用 UIHostingController……如果您不厌其烦地使用 UITableView,为什么不在 UIKit 中也制作单元格呢?或者,如果您需要 SwiftUI 来处理行,为什么不使用 List 而不是托管 UITableView?
来自苹果:
感谢您的反馈,已记录。工程部门已确定目前没有解决此问题的计划。
我们建议使用 List,并针对 List 无法提供的任何需求提交单独的增强。
我正在尝试将 UITableView 与 UIViewRepresantable 一起使用,它有点管用,但不是真的。有些行放置在错误的位置,要么与其他行重叠,要么添加了额外的填充。此外,即使我设置了 automaticDimension,它似乎也不会使行高适应行的内容。
这是演示:
代码如下:
import SwiftUI
struct ContentView: View {
@State var rows : [String] = []
var listData = ListData()
var body: some View {
VStack {
Button(action: {
self.getDataFromTheServer()
}) {
Text("Get 100 entries from the server")
}
UIList(rows: $rows)
}
}
func getDataFromTheServer() {
for _ in 1...100 {
self.rows.append(self.listData.data)
self.listData.data.append("a")
}
}
}
class ListData {
var data: String = ""
}
class HostingCell: UITableViewCell {
var host: UIHostingController<AnyView>?
}
struct UIList: UIViewRepresentable {
@Binding var rows: [String]
func makeUIView(context: Context) -> UITableView {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.dataSource = context.coordinator
tableView.delegate = context.coordinator
tableView.register(HostingCell.self, forCellReuseIdentifier: "Cell")
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
return tableView
}
func updateUIView(_ uiView: UITableView, context: Context) {
DispatchQueue.main.async {
uiView.reloadData()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(rows: $rows)
}
class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {
@Binding var rows: [String]
init(rows: Binding<[String]>) {
self._rows = rows
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.rows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! HostingCell
let view = Text(rows[indexPath.row])
.background(Color.blue)
.lineLimit(nil)
// create & setup hosting controller only once
if tableViewCell.host == nil {
let hostingController = UIHostingController(rootView: AnyView(view))
tableViewCell.host = hostingController
let tableCellViewContent = hostingController.view!
tableCellViewContent.translatesAutoresizingMaskIntoConstraints = false
tableViewCell.contentView.addSubview(tableCellViewContent)
tableCellViewContent.topAnchor.constraint(equalTo: tableViewCell.contentView.topAnchor).isActive = true
tableCellViewContent.leftAnchor.constraint(equalTo: tableViewCell.contentView.leftAnchor).isActive = true
tableCellViewContent.bottomAnchor.constraint(equalTo: tableViewCell.contentView.bottomAnchor).isActive = true
tableCellViewContent.rightAnchor.constraint(equalTo: tableViewCell.contentView.rightAnchor).isActive = true
} else {
// reused cell, so just set other SwiftUI root view
tableViewCell.host?.rootView = AnyView(view)
}
tableViewCell.setNeedsLayout()
return tableViewCell
}
}
}
UIHostingControllers 不能很好地调整自己的大小,我怀疑这是破坏自动布局的原因。尝试在设置控制器的 rootView 后添加:
hostingController.preferredContentSize = hostingController.sizeThatFits( )
就是说,您可能想完全避免使用 UIHostingController……如果您不厌其烦地使用 UITableView,为什么不在 UIKit 中也制作单元格呢?或者,如果您需要 SwiftUI 来处理行,为什么不使用 List 而不是托管 UITableView?
来自苹果:
感谢您的反馈,已记录。工程部门已确定目前没有解决此问题的计划。
我们建议使用 List,并针对 List 无法提供的任何需求提交单独的增强。