8

I'm experimenting with the new NSCollectionView API, introduced in El Capitan.

Following the WWDC video, I create a subclass of NSCollectionViewFlowLayout to determine the layout of the collection view.

class Layout : NSCollectionViewFlowLayout {

  override func prepareLayout() {

    super.prepareLayout()

    self.minimumInteritemSpacing = 0
    self.minimumLineSpacing = 0

    let cheight = self.collectionView!.bounds.height
    let cwidth = self.collectionView!.bounds.width

    self.itemSize = CGSizeMake(cwidth / 2.0, cheight / 6.0)

  }

}

After that, I've created a NSObject subclass to serve as data source.

class DataSource : NSObject, NSCollectionViewDataSource {

  func collectionView(collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5
  }

  func collectionView(collectionView: NSCollectionView, itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem {

    /* DOESN'T GET CALLED! */

    let item = collectionView.makeItemWithIdentifier("cell", forIndexPath: indexPath)

    item.view.wantsLayer = true
    item.view.layer?.backgroundColor = NSColor.redColor().CGColor

    return item

  }

}

The issue is that collectionView:itemForRepresentedObjectAtIndexPath: never gets called.

This is how I initialise the collection view:

let collectionView = NSCollectionView(frame: view.bounds)

let dataSource = DataSource()
let layout = Layout()

collectionView.collectionViewLayout = layout
collectionView.registerClass(NSCollectionViewItem.self,     
                             forItemWithIdentifier: "cell")
collectionView.dataSource = dataSource

collectionView.backgroundColors = [.blackColor()]

I can clearly see the collection view in its superview, but there are no cells.

Also, this line, if called outside the delegate (but after the cell class is registered) makes the app crash!

let item = collectionView.makeItemWithIdentifier("cell", forIndexPath: /*any index path*/)

Am I doing something wrong or is NSCollectionView new API broken?

Thanks.

Matteo Pacini
  • 21,796
  • 7
  • 67
  • 74
  • This is probably a stupid question but you are adding the collection view to your view's subviews, right? – Aaron Feb 24 '16 at 00:32
  • @Aaron I am. I can see the collection view in its superview (without cells) – Matteo Pacini Feb 24 '16 at 06:11
  • 1
    how do you know the method was not called? did you set some breakpoint up inside that method? or tried to log something inside the method's body? is your `cell.xib` file in the same bundle? or do you create the interface programmatically (as you have registered a _class_ but not a _nib_)? have you changed the collection view's flow form _"legacy"_ to e.g. _"flow"_ in IB? – holex Feb 25 '16 at 10:20
  • @holex I tried both. There are no .XIBs. – Matteo Pacini Feb 26 '16 at 17:44
  • @MatteoPacini, you have _zero_ `.xib` file in your project? – holex Feb 29 '16 at 09:03
  • Possible duplicate of [Creating NSCollectionView with datasource programatically](http://stackoverflow.com/questions/36230928/creating-nscollectionview-with-datasource-programatically) – corro Apr 04 '16 at 16:31

3 Answers3

0

The method makeItemWithIdentifier is crucial and looks for .xib named "cell" in you bundle: you may need register it with registerNib:forItemWithIdentifier: if it comes from another bundle.

Thus your problem comes before that, since your collectionView:itemForRepresentedObjectAtIndexPath never gets called and this could arise from your pattern: why do you create a new class to serve as datasource and not use the same NSViewController where the NSCollectionView resides?

I always do so and with the new API all works perfectly. Hope this could help you!

  • I'm trying to create the collection view programmatically, that's why I'm using `registerClass:forItemWithIdentifier:` rather than `registerNib:forItemWIthIdentifier`. – Matteo Pacini Feb 26 '16 at 17:47
  • I've also tried both registerClass and registerNib without luck. numberOfItemsInSection gets called but itemForRepresentedObjectAtIndexPath doesn't. – empedocle Mar 23 '16 at 02:36
0

I had almost the same problem, and here is how I solved it.

First of all the problem I had :

  • when my collection view delegate was NOT implementing the NSCollectionViewDelegateFlowLayout protocol, everything was fine and the collectionView:itemForRepresentedObjectAtIndexPath method was called
  • when my collection view delegate was implementing the NSCollectionViewDelegateFlowLayout protocol, collectionView:itemForRepresentedObjectAtIndexPath method was NOT called

I commented out every NSCollectionViewDelegateFlowLayout method in the delegate, and it turned out that if the method collectionView:layout:referenceSizeForHeaderInSection: was commented out, then everything was fine again (though I don't use headers).

It turned out that collectionView:layout:referenceSizeForHeaderInSection: was returning a NaN instead of 0.0 as the width in the size (stupid copy/paste mistake).

Are you sure you don't have the same kind of problem in what your layout is returning ?

AirXygène
  • 2,409
  • 15
  • 34
0

The issue I was having was that I didn't register either nib or class for the items of the collection view. The symptoms were exactly like those you describe -- numberOfItemsInSection was called, and itemForRepresentedObjectAtIndexPath was not. After registering a nib, the method started being invoked. Here's the relevant answer -- https://stackoverflow.com/a/39516035/4635852

Aleksey Gureiev
  • 1,729
  • 15
  • 17