如何在UIViewRepresentable SwiftUI中重新加载collectionview

时间:2020-02-26 17:55:39

标签: ios swift uicollectionview swiftui uiviewrepresentable

##如何在UIViewRepresentable ##中重新加载集合视图

使用UIViewRepresentable和集合视图,在迭代后进入reload()集合视图时会卡住,如何通过数据进行迭代时如何在UIViewRepresentable中重新加载集合视图? func updateUIView不起作用。


    struct VideoCollectionView: UIViewRepresentable {

        var data: VideoViewModel

        @Binding var search: String

        var dataSearch: [VideoPostModel] {
            if search.isEmpty {
                return data.postsSearch
            }else{
                let d = data.postsSearch.filter {$0.artistname.localizedStandardContains(search)}
                return d
            }
        }

        var didSelectItem: ((_ indexPath: IndexPath)->()) = {_ in }
        var didSelectObject: ((_ boject: VideoPostModel)->()) = {_ in }

        func makeUIView(context: Context) -> UICollectionView {
            let reuseId = "AlbumPrivateCell"

            let collection :UICollectionView = {
                let layout = UICollectionViewFlowLayout()
                layout.sectionHeadersPinToVisibleBounds = true
                let collectionV = UICollectionView(frame: .zero, collectionViewLayout: layout)
                layout.scrollDirection = .vertical
                collectionV.translatesAutoresizingMaskIntoConstraints = false
                collectionV.backgroundColor = .clear
                collectionV.dataSource = context.coordinator
                collectionV.delegate = context.coordinator
                collectionV.register(AlbumPrivateCell.self, forCellWithReuseIdentifier: reuseId)

                return collectionV
            }()

            return collection
        }
        func updateUIView(_ collectionView: UICollectionView, context: UIViewRepresentableContext<VideoCollectionView>) {
            print("updateUIView updateUIView")
            print(search)

            collectionView.reloadData() 
        }
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }

        class Coordinator: NSObject, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

            private var parent: VideoCollectionView
            init(_ albumGridView: VideoCollectionView) {
                self.parent = albumGridView
            }
            func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
                return self.parent.dataSearch.count
            }
            func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AlbumPrivateCell", for: indexPath) as! AlbumPrivateCell
                    cell.data = self.parent.dataSearch[indexPath.item]
                return cell
            }
            func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
                let post = self.parent.dataSearch[indexPath.item]
                parent.didSelectItem(indexPath)
                parent.didSelectObject(post)
            }
            func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
                let width = collectionView.frame.width
                let height = collectionView.frame.height/2
                return CGSize(width: width, height: height)
            }

        }
    }

3 个答案:

答案 0 :(得分:0)

现在处理此问题,唯一的方法是我能够创建reloadData,是在Coordinator类中创建引用并将其传递给创建者:

context.coordinator.collectionView = collectionView

您可以从那里调用reloadData(),当然,可以确定有更优雅的方法来实现此目的。

编辑:回答请求以扩展我的方法。

假设您有一个这样的协调员:

class CoordinatorItemPicturesView: NSObject, UICollectionViewDataSource, UICollectionViewDelegate {
// MARK: - Properties
var collectionView: UICollectionView!
var elements = [String]()
init(elements:[String]) {
    self.elements = elements
}

// MARK: UICollectionViewDataSource

func collectionView(_: UICollectionView, numberOfItemsInSection _: Int) -> Int {
    return elements.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    return  UICollectionViewCell()
}
}

因此,当您创建UIViewRepresentable时,请传递collectionView引用:

struct ItemPicturesView: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<ItemPicturesView>) -> UICollectionView {
    /// Set Context, cells, etc
    let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
    collectionView.backgroundColor = .clear
    collectionView.translatesAutoresizingMaskIntoConstraints = false
    collectionView.dataSource = context.coordinator
    collectionView.delegate = context.coordinator
    collectionView.isScrollEnabled = true
    // --- Right here
    context.coordinator.collectionView = collectionView
    return collectionView
}

func updateUIView(_ uiView: UICollectionView, context _: Context) {
    UIView.animate(withDuration: 1.0) {
        uiView.frame = uiView.frame
        uiView.reloadData()
    }
}

func makeCoordinator() -> CoordinatorItemPicturesView {
    CoordinatorItemPicturesView(elements:["Element One", "Element Two"])
}
}

很抱歉,如果代码不是100%完美,就必须从具有NDA的项目中获取它,并且不对删除的属性进行测试。

答案 1 :(得分:0)

UIViewRepresentable只是一个包装器。 您必须将您的模型设为可观察。那么它将在数据发生任何变化时自动更新。

答案 2 :(得分:0)

您需要做的就是将data中的VideoCollectionView属性设置为:

@Binding var data: VideoViewModel

现在,一旦更新数据,更新视图将重新加载collectionView。 说明: 您的数据属性(值类型)应为Binding属性,因为Coordinator依赖于此。当您使用self初始化Coordinator时,您正在传递data属性的旧实例。将其更改为绑定可以使其变异。