0

Je rencontre un problème avec l'implémentation d'un scrollToItem collectionView horizontal. J'ai un collectionView (menuBar) que sur le robinet d'une cellule, la collection de pages défilera horizontalement à la cellule appropriée. À la pression de la collection menuBar ViewCell l'application se bloque. Je ne sais pas où l'erreur est. Merci d'avance!défilement horizontal scrollToItem collectionCoupure

// contrôleur classe

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 classe bar

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") 
    } 

} 
+0

Quelle erreur? Aussi, comme je peux vous voir, essayez de faire défiler deux vues de collection différentes, peut-être que c'est le point? BTW, dans votre MenuBar 'var currentUserPlaceDetailsVC: CurrentUserPlaceDetailsVC?' Devrait être 'faible '. –

+0

Bonjour - J'obtiens l'erreur "se terminant avec l'exception non interceptée de type NSException". – user3708224

+0

pouvez-vous fournir tous les messages d'erreur? avec la trace de pile et etc. –

Répondre

0

Dans votre commentaire, vous avez dit:

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.

Cela arrive, parce que vous dans votre vue Contrôler votre collectionView déclaré comme paresseux, cela signifie qu'il sera être calculé sur demande. Le problème est dans l'initialisation de votre CollectionView (reason: 'UICollectionView must be initialized with a non-nil layout parameter')

Dans votre contrôleur de vue de remplacer l'initialisation UICollectionView avec ce code:

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 
}() 

post-scriptum Comme je l'ai écrit dans mon commentaire à votre question, vous avez reference cycle. La classe MenuBar doit contenir une référence faible à votre contrôleur de vue pour l'empêcher.

+0

Merci ... cela m'a aidé mais j'ai aussi compris que mes contraintes UICollectionViewFlowLayout posaient quelques problèmes. J'ai dû ajouter le code suivant à ma méthode setupCollectionView(). si let flowLayout = contentCollectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.scrollDirection = .horizontal flowLayout.minimumLineSpacing = 0} – user3708224

+0

vous pouvez le régler directement après 'laisser layout = UICollectionViewFlowLayout()' cette ligne, comme vous l'avez fait dans votre classe 'MenuBar' :). –