Swift NSCollectionView flow from bottom to top

398 Views Asked by At

I am workin on a messaging client for macOS, written in Swift. I use an NSScrollView with an NSCollectionView as the documentView to present the messages. Currently, I have implemented infinite scrolling, but now the problem is that the collectionView loads the cells starting at the top and works its way down – the default behavior for an NSCollectionView. Instead, I need it to start at the bottom and work its way up – the way that a typical messaging application displays messages.

Solutions I have tried:

  • Scrolling to the bottom of the collectionView as soon as the view loads or the user selects a different conversation. This solution is visibly janky and truly messes up infinite scrolling.
  • Overriding the isFlipped variable in the scrollView, the scrollView's contentView, and the collectionView. Doing this has had zero visible effect on any of the views.
  • Rotating the entire scrollView, collectionView, contentView, or collectionView cells by pi radians. As a desperate measure, I attempted to rotate the entire scrollView and was not able to do that nor rotate any of the collectionView items. I did something along the lines of wantsLayer = true layer!.setAffineTransform(CGAffineTransform(rotationAngle: .pi)) updateLayer() setNeedsDisplay(frameRect). This again has no visible affect.

What's the best way to go about getting the NSCollectionView to go from bottom to top? By the way, I am not using Storyboards.

1

There are 1 best solutions below

0
On

Hi @will i am not sure if this code will help you, because i have used it for iPhone chat application and it works for me. In my case i have simply put collectionView in view controller.

//MARK:- View Controller life cycle method
override func viewDidLoad() {
  chatCollectionView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  if(keyPath == "contentSize"){
    if let newvalue = change?[.newKey] {
        let contentHeight: CGFloat = chatCollectionView.contentSize.height
        let collectionHeight = chatCollectionView.frame.size.height
        if contentHeight < collectionHeight {
            var insets: UIEdgeInsets = chatCollectionView.contentInset
            insets.top = collectionHeight - contentHeight
            chatCollectionView.contentInset = insets
        } else {
            chatCollectionView.contentInset = .zero
        }
    }
  }
}

override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  chatCollectionView.removeObserver(self, forKeyPath: "contentSize")
}