如何在 UIViewRepresentable SwiftUI 中重新加载集合视图
Posted
技术标签:
【中文标题】如何在 UIViewRepresentable SwiftUI 中重新加载集合视图【英文标题】:How to reload collectionview in UIViewRepresentable SwiftUI 【发布时间】:2020-02-26 17:55:39 【问题描述】:## 如何在 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)
【问题讨论】:
嗨,你得到解决方案了吗,我也卡在这里,如果你得到解决方案,请告诉我 @VivekKumarSamele 查看我的解决方案。这可能会有所帮助。 【参考方案1】:现在处理这个问题,我能够制作 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 的项目中获取它,并且没有使用已删除的属性进行测试。
【讨论】:
你好威尔逊,可以分享你如何传递参考的代码吗?? @VivekKumarSamele 刚刚做了,让我知道你的想法。 谢谢,够了【参考方案2】:UIViewRepresentable 只是一个包装器。 你必须让你的模型成为可观察的。然后它会在数据发生任何变化时自动更新。
【讨论】:
【参考方案3】:您需要做的就是将VideoCollectionView
中的data
属性设为:
@Binding var data: VideoViewModel
现在一旦你更新数据,你更新的视图会重新加载collectionView。
解释:
您的数据属性(值类型)应该是 Binding 属性,因为 Coordinator
取决于它。当您使用 self 初始化 Coordinator 时,您正在传递数据属性的旧实例。将其更改为绑定允许对其进行变异。
【讨论】:
以上是关于如何在 UIViewRepresentable SwiftUI 中重新加载集合视图的主要内容,如果未能解决你的问题,请参考以下文章
如何在解雇后停止播放 AVPlayerViewController 作为 UIViewRepresentable?
如何在 SwiftUI 中结束 UIViewRepresentable 的编辑?
SwiftUI:如何调整 UIViewRepresentable 输出的大小?
如何找到 SwiftUI UIViewRepresentable 的框架