【问题标题】:TableView Reload Not working with UIViewRepresentable in SwiftUITableView 重新加载不适用于 SwiftUI 中的 UIViewRepresentable
【发布时间】:2020-08-06 14:09:26
【问题描述】:

在收到 API 响应后,我正在尝试重新加载 tableView。 TableView 重新加载不会调用cellForRowAt,因为它最初是用空项目初始化的。我添加了复制问题所需的最少代码。

UIViewRepresentable的代码

import SwiftUI
import UIKit

struct UIListView: UIViewRepresentable {
    
    @Binding var reload: Bool
    
    var items: [String]
    private let tableView =  UITableView()
    
    func makeUIView(context: Context) -> UITableView {
        print("*************** make")
        tableView.dataSource = context.coordinator
        return tableView
    }
    
    func updateUIView(_ uiView: UITableView, context: Context) {
        print("*************** update", items.count)
        print("********* RELOAD", reload)
        if reload {
            DispatchQueue.main.async {
                //                uiView.reloadData()
                //                tableView.reloadData()
                context.coordinator.reload()
            }
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}

extension UIListView {
    
    final class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {
        
        private var parent: UIListView
        
        init(_ parent: UIListView) {
            self.parent = parent
        }
        
        func reload() {
            parent.tableView.reloadData()
        }
        
        //MARK: UITableViewDataSource Methods
        
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return parent.items.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            print("*********Cell for row at")
            let cell = UITableViewCell()
            cell.textLabel?.text = parent.items[indexPath.row]
            return cell
        }
    }
}

CustomListView 和 ViewModel 的代码

    struct CustomListView: View {
    @ObservedObject var model = VM()
    
    var body: some View {
        print("******* BODY")
        return UIListView(reload: $model.reload, items: model.items)
            .onAppear {
                model.fetchData()
            }
    }
}

class VM: ObservableObject {
    
    @Published var reload = false
    var items = [String]()
    
    func fetchData() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.items = ["asdas", "asdasdas"]
            self.reload.toggle()
        }
    }
}

【问题讨论】:

    标签: uitableview swiftui uiviewrepresentable


    【解决方案1】:

    我假设 UITableView 成员刚刚重新创建,因为它是成员,而是如下使用

    使用 Xcode 12 / iOS 14 测试

    struct CustomListView: View {
        @StateObject var model = VM()
    
        var body: some View {
            print("******* BODY")
            return UIListView(reload: $model.reload, items: $model.items)
                .onAppear {
                    model.fetchData()
                }
        }
    }
    
    class VM: ObservableObject {
    
        @Published var reload = false
        var items = [String]()
    
        func fetchData() {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                self.items = ["asdas", "asdasdas"]
                self.reload.toggle()
            }
        }
    }
    
    struct UIListView: UIViewRepresentable {
    
        @Binding var reload: Bool
        @Binding var items: [String]
    
        func makeUIView(context: Context) -> UITableView {
            print("*************** make")
            let tableView =  UITableView()
            tableView.dataSource = context.coordinator
            return tableView
        }
    
        func updateUIView(_ tableView: UITableView, context: Context) {
            print("*************** update", items.count)
            print("********* RELOAD", reload)
            if reload {
                DispatchQueue.main.async {
                    tableView.reloadData()
                }
            }
        }
    
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
    }
    
    extension UIListView {
    
        final class Coordinator: NSObject, UITableViewDataSource, UITableViewDelegate {
    
            private var parent: UIListView
    
            init(_ parent: UIListView) {
                self.parent = parent
            }
    
            //MARK: UITableViewDataSource Methods
    
            func numberOfSections(in tableView: UITableView) -> Int {
                return 1
            }
    
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return parent.items.count
            }
    
            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                print("*********Cell for row at")
                let cell = UITableViewCell()
                cell.textLabel?.text = parent.items[indexPath.row]
                return cell
            }
        }
    }
    

    【讨论】:

    • 它对你有用吗?它在 Xcode beta 3 上对我不起作用,已经尝试过你提到的方式。
    • 很好用。你有什么解释为什么只使用 reload as Binding 不起作用?
    • items 是值和结构的一部分,所以Coordinator init 只是复制空并存储它。绑定允许访问可更新的数据存储。
    • 现在这对我来说很有意义,这意味着如果我删除重新加载绑定,它应该仍然可以工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 2019-12-28
    • 2021-08-20
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    相关资源
    最近更新 更多