我正在研究一个灵活的表单组件,该组件基本上由具有集合视图的UIViewController组成,该视图可以具有该类的无限嵌套的视图控制器。 在当前状态下,它或多或少都可以正常工作,但是不幸的是滚动不稳定,而且我还没有找到解决该问题的方法。也许你们当中有人想出一个好的解决方案。 我还尝试过缓存视图控制器,这有助于实现平滑的滚动,但是不幸的是,有了该解决方案,我开始出现显示问题。有时,单元格中的内容只是消失了,我无法弄清原因。
以下是整个项目的链接: https://d.pr/f/0ij57m
该项目的主要部分基本上是这个FlexibleViewController(通过情节提要设计)
class FlexibleViewController: UIViewController {
var dataForDatasource = Array<Component>()
var datasource: UICollectionViewDataSource?
@IBOutlet var collectionView: UICollectionView! {
didSet {
let datasource = MyDatasource(data: dataForDatasource, parentController: self)
self.datasource = datasource
self.collectionView.dataSource = datasource
self.collectionView.delegate = datasource
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.view.setNeedsLayout()
self.collectionView?.collectionViewLayout.invalidateLayout()
}
func invalidateLayout() {
self.collectionView.collectionViewLayout.invalidateLayout()
if let controller = self.parent as? FlexibleViewController {
controller.invalidateLayout()
}
}
}
此数据源:
class MyDatasource: NSObject, UICollectionViewDataSource, UICollectionViewDelegate {
weak var parentController: UIViewController!
var components: Array<Component>!
init(data: Array<Component>, parentController: UIViewController) {
self.components = data
self.parentController = parentController
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return components.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let component = components[indexPath.row]
var cell: UICollectionViewCell?
if component.subComponents.count > 0 {
let collectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collection", for: indexPath) as! TestCell
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vs = storyboard.instantiateViewController(withIdentifier: "flexi") as! FlexibleViewController
vs.dataForDatasource = component.subComponents
parentController.addChild(vs)
collectionCell.addSubview(vs.view)
vs.collectionView.backgroundColor = component.backgroundColor
vs.didMove(toParent: parentController)
collectionCell.controller = vs
cell = collectionCell
} else {
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "default", for: indexPath)
cell!.backgroundColor = component.backgroundColor
}
return cell!
}
}
extension MyDatasource: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var sizeForItem: CGSize
let component = components[indexPath.row]
var width = Int(collectionView.frame.size.width)
if component.width != -1 && component.width < width {
width = component.width
}
var height: Int = 50
if component.subComponents.count > 0 {
let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: width, height: height), collectionViewLayout: UICollectionViewFlowLayout())
let datasource = MyDatasource(data: component.subComponents, parentController: UIViewController())
collectionView.dataSource = datasource
collectionView.delegate = datasource
collectionView.reloadData()
height = Int(collectionView.collectionViewLayout.collectionViewContentSize.height)
sizeForItem = CGSize(width: width, height: height)
} else {
sizeForItem = CGSize(width: width, height: height)
}
return sizeForItem
}
}
如您所见,当该组件具有多个组件时,将通过情节提要实例化具有集合视图的新控制器,这可能并不理想(尽管并不像我预期的那样昂贵)。我试图重新初始化viewDidLoad中的所有控制器,但是就像我在介绍中所说的那样,该解决方案遇到显示问题。
该单元格非常简单,看起来像这样:
class TestCell: UICollectionViewCell {
var controller: UIViewController?
override func prepareForReuse() {
super.prepareForReuse()
controller?.willMove(toParent: nil)
controller?.removeFromParent()
controller?.view.removeFromSuperview()
}
}
组件类如下:
class Component {
var generatedId = NSUUID().uuidString
var identifier: String?
var subComponents = Array<Component>()
var width: Int! = -1
var type: String! = "default"
var backgroundColor: UIColor! = .white
var isOpen: Bool = false
}
在此先感谢您的帮助! :-)
答案 0 :(得分:0)
您应该查看有关Prefetching Collection View Data的Apple出色的文档
它包含一个(快速)示例项目,并大量使用OperationQueue
和NSCache
。
基本思想是“预取”并缓存下一个项目,然后显示它们以平滑滚动。向后滚动时,将从缓存中获取项目。