SwiftUI 中带有 UIViewRepresentable 的 UITableView

UITableView with UIViewRepresentable in SwiftUI(SwiftUI 中带有 UIViewRepresentable 的 UITableView)

本文介绍了SwiftUI 中带有 UIViewRepresentable 的 UITableView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 SwiftUI 应用中使用 UITableView

I am trying to use UITableView in a SwiftUI app

struct UIList: UIViewRepresentable {

    var rows: [String]

    func makeUIView(context: Context) -> UITableView {
        let collectionView = UITableView(frame: .zero, style: .plain)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.dataSource = context.coordinator
        collectionView.delegate = context.coordinator
        collectionView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        return collectionView
    }

    func updateUIView(_ uiView: UITableView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(rows: rows)
    }

    class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {

        var rows: [String]

        init(rows: [String]) {
            self.rows = rows
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            self.rows.count
        }

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) //as! AlbumPrivateCell

            let view = Text(rows[indexPath.row]).frame(height: 50).background(Color.blue)// UIFactory(appComponent:

            let controller = UIHostingController(rootView: view)

            let tableCellViewContent = controller.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


            return tableViewCell
        }
    }
}

当我快速滚动表格时,单元格内容会在每个单元格的顶部和底部随机填充,知道为什么会发生这种情况吗?

When I scroll the table quickly the cells content get a random padding at top and bottom of each cell, any idea why this happens ?

PS:我知道我可以使用 List ,我尝试使用 UITableView 因为我必须添加多个滑动操作,但 List 只允许一次滑动操作(删除)

PS: I know I could use List , I try to use UITableView because I have to add multiple swipe actions, but List only allows one swipe action (delete)

推荐答案

我认为这是由于重复使用的表视图单元格损坏......(并且可能丢失了主机控制器,因为那里是在堆栈上创建的,而不是存储在任何地方)

I assume this is due to corrupted reused table view cells... (and probably lost hosting controllers, because there where created on stack and not stored anywhere)

请在下面找到通过提到的修复更正了您的代码.经过测试使用 Xcode 11.2/iOS 13.2.

Please find below corrected a bit your code with mentioned fixes. Tested & worked with Xcode 11.2 / iOS 13.2.

这是代码(内嵌一些注释):

Here is code (with some comments inline):

class HostingCell: UITableViewCell { // just to hold hosting controller
    var host: UIHostingController<AnyView>?
}

struct UIList: UIViewRepresentable {

    var rows: [String]

    func makeUIView(context: Context) -> UITableView {
        let collectionView = UITableView(frame: .zero, style: .plain)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.dataSource = context.coordinator
        collectionView.delegate = context.coordinator
        collectionView.register(HostingCell.self, forCellReuseIdentifier: "Cell")
        return collectionView
    }

    func updateUIView(_ uiView: UITableView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(rows: rows)
    }

    class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {

        var rows: [String]

        init(rows: [String]) {
            self.rows = rows
        }

        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            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])
                    .frame(height: 50).background(Color.blue)

            // create & setup hosting controller only once
            if tableViewCell.host == nil {
                let controller = UIHostingController(rootView: AnyView(view))
                tableViewCell.host = controller

                let tableCellViewContent = controller.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
        }
    }
}

UIList 本身添加了演示代码 - 也适用于专业模型.

Added demo code for just UIList itself - works fine with pro models as well.

struct TestUIList: View {
    var body: some View {
        UIList(rows: generateRows())
    }

    func generateRows() -> [String] {
        (0..<100).reduce([]) { $0 + ["Row ($1)"] }
    }
}

这篇关于SwiftUI 中带有 UIViewRepresentable 的 UITableView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:SwiftUI 中带有 UIViewRepresentable 的 UITableView

基础教程推荐