简体   繁体   English

scrollToItem水平滚动collectionView崩溃

[英]scrollToItem horizontal scrolling collectionView crash

I am having an issue with implementing a horizontal scrollToItem collectionView. 我在实现水平scrollToItem collectionView时遇到问题。 I have a collectionView (menuBar) that on tap of a cell the page collectionView will horizontally scroll to the appropriate cell. 我有一个collectionView(menuBar),在单击某个单元格时,页面collectionView将水平滚动到相应的单元格。 On tap of the menuBar collectionViewCell the app crashes. 点击menuBar collectionViewCell时,应用崩溃。 Not sure where the error is. 不知道错误在哪里。 Thanks in advance! 提前致谢!

// controller class //控制器类

class CurrentUserPlaceDetailsVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    var titleText: String?

    let cellId = "cellId"

    // UI elements
    lazy var contentCollectionView: UICollectionView = {
        let cv = UICollectionView()
        cv.backgroundColor = UIColor.red
        cv.layer.zPosition = 0
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.layer.masksToBounds = true
        return cv
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupMenuBar()
        setupCollectionView()

    }

    func scrollToMenuIndex(_ menuIndex: Int) {
        let indexPath = IndexPath(item: menuIndex, section: 0)
        contentCollectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition(), animated: true)
    }

    lazy var menuBar: MenuBar = {
        let mb = MenuBar()
        mb.currentUserPlaceDetailsVC = self
        return mb
    }()

    private func setupMenuBar() {
        view.addSubview(menuBar)
        view.addConstraintsWithFormat("H:|[v0]|", views: menuBar)
        view.addConstraintsWithFormat("V:|[v0(114)]", views: menuBar)
    }

    func setupCollectionView() {

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()

        layout.scrollDirection = .horizontal
        layout.minimumLineSpacing = 0
//        layout.sectionInset = UIEdgeInsets(top: 0, left: 10, bottom: 10, right: 10)
        layout.itemSize = CGSize(width: self.view.frame.width, height: self.view.frame.height)

        let contentCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        contentCollectionView.dataSource = self
        contentCollectionView.delegate = self

        // register cells
        contentCollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cellId")
        contentCollectionView.backgroundColor = .white
//        contentCollectionView.scrollIndicatorInsets = UIEdgeInsets(top:114, left: 10, bottom: 10, right: 10)
        self.view.addSubview(contentCollectionView)

        _ = contentCollectionView.anchor(view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, topConstant: 114, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)
        view.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        contentCollectionView.isPagingEnabled = true
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print(scrollView.contentOffset.x)
        menuBar.horizontalBarLeftAnchorConstraint?.constant = scrollView.contentOffset.x / 4
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath)
        let colors: [UIColor] = [.blue, .red, .yellow, .green]
        myCell.backgroundColor = colors[indexPath.item]
        return myCell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: view.frame.height)
    }

}

// menu bar class //菜单栏类

class MenuBar: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.minimumLineSpacing = 0
        layout.headerReferenceSize = .zero
        layout.sectionInset = .zero
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .green
        cv.dataSource = self
        cv.delegate = self
        return cv
    }()

    let cellId = "cellId"

    var currentUserPlaceDetailsVC: CurrentUserPlaceDetailsVC?

    override init(frame: CGRect) {
        super.init(frame: frame)

        collectionView.register(MenuCell.self, forCellWithReuseIdentifier: cellId)

        addSubview(collectionView)
        addConstraintsWithFormat("H:|[v0]|", views: collectionView)
        addConstraintsWithFormat("V:|[v0]|", views: collectionView)

        let selectedIndexPath = IndexPath(item: 0, section: 0)
        collectionView.selectItem(at: selectedIndexPath, animated: false, scrollPosition: UICollectionViewScrollPosition())

        setupHorizontalBar()
    }

    var horizontalBarLeftAnchorConstraint: NSLayoutConstraint?

    func setupHorizontalBar() {
        let horizontalBarView = UIView()
        horizontalBarView.backgroundColor = .white
        horizontalBarView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(horizontalBarView)

        horizontalBarLeftAnchorConstraint = horizontalBarView.leftAnchor.constraint(equalTo: self.leftAnchor)
        horizontalBarLeftAnchorConstraint?.isActive = true

        horizontalBarView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        horizontalBarView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/4).isActive = true
        horizontalBarView.heightAnchor.constraint(equalToConstant: 4).isActive = true

    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print(indexPath.item)
        let x = CGFloat(indexPath.item) * frame.width / 4
        horizontalBarLeftAnchorConstraint?.constant = x

        UIView.animate(withDuration: 0.75, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            self.layoutIfNeeded()
        }, completion: nil)

        currentUserPlaceDetailsVC?.scrollToMenuIndex(indexPath.item)

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 4
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MenuCell
        cell.imageView.image = UIImage(named: imageNames[indexPath.item])?.withRenderingMode(.alwaysTemplate)
        cell.tintColor = UIColor.rgb(91, green: 14, blue: 13)

        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: frame.width / 4, height: frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

In your comment you said: 在您的评论中,您说:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'. I believe there is something wrong in my func scrollToMenuIndex()... when I remove that func the app does not crash.

That happens, because you inside your View Controller your collectionView declared as lazy, that means it will be calculated on-demand. 发生这种情况是因为您在View Controller中将collectionView声明为lazy,这意味着它将按需计算。 The problem is in initializing your collectionView ( reason: 'UICollectionView must be initialized with a non-nil layout parameter' ) 问题在于初始化collectionView( reason: 'UICollectionView must be initialized with a non-nil layout parameter'

In your view controller replace UICollectionView initialization with this code: 在您的视图控制器中,使用以下代码替换UICollectionView初始化:

lazy var contentCollectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = UIColor.red
    cv.layer.zPosition = 0
    cv.translatesAutoresizingMaskIntoConstraints = false
    cv.layer.masksToBounds = true
    return cv
}()

PS As I wrote in my comment to your question, you have reference cycle . 附言:正如我在对您的问题的评论中所写的那样,您具有参考周期 class MenuBar should hold weak reference to your view controller to prevent this. MenuBar类应保持对视图控制器的弱引用,以防止出现这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 给 CollectionView 的 scrollToItem 方法添加一个闭包 - Add a closure to scrollToItem method of CollectionView CollectionView:scrollToItem,reloadData和调度队列 - CollectionView: scrollToItem, reloadData, and Dispatch Queues 滚动水平collectionview时的随机行为 - random behavior when scrolling a horizontal collectionview tableview单元格横向collectionview滚动问题 - The problem of scrolling of horizontal collectionview in tableview cell collectionView 不 scrollToItem - swift - 以编程方式 - collectionView doesn't scrollToItem - swift - programmatically scrollToItem 在我的 CollectionView 中不起作用? - scrollToItem isn't working in my CollectionView? 调整 collectionView.scrollToItem 以考虑插入? - Adjust collectionView.scrollToItem to consider inset? "当单元格不是屏幕大小时,CollectionView 水平滚动和分页 - Swift" - CollectionView horizontal scrolling with pagning when cells are not screen size - Swift 当collectionview布局的滚动方向为Horizo​​ntal时,如何设置referenceSizeForHeaderInSection? - How to set referenceSizeForHeaderInSection when the collectionview layout scrolling direction is Horizontal? 在水平滚动中使用不同宽度的单元格设置collectionView的大小 - Set the size of a collectionView with cell of different width, in a horizontal scrolling
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM