swiftcocoanscollectionviewnscollectionviewitem

NSCollectionViewItem has nil outlets in itemForRepresentedObjectAtIndexPath


I have an NSCollectionView that displays a bunch of items that are called "ImageCollectionViewItem"s. I have an ImageCollectionViewItem.xib file that solely has an NSView that covers the item. I want to be able to dynamically change what is in that view, but when I try to reference it, it is nil. I already checked questions like: outlets in UIViewController nil in viewdidload , that is not my problem, I linked it and I have the filled circle

Here is the viewcontroller extension:

extension ViewController : NSCollectionViewDataSource {

    func collectionView(collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
        return titles.count
    }
    func collectionView(collectionView: NSCollectionView, itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem {
        let item = collectionView.makeItemWithIdentifier("ImageCollectionViewItem", forIndexPath: indexPath) as! ImageCollectionViewItem

        //This is what is nil:
        let thisView = item.iconView

        return item
    }

}

And then here is the ImageViewCollectionItem code

class ImageCollectionViewItem: NSCollectionViewItem {

    @IBOutlet weak var iconView: NSView!

    var numItem: Int?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do view setup here.

        view.wantsLayer = true
        view.layer?.backgroundColor = NSColor.whiteColor().CGColor
    }
}

Solution

  • That is some odd stuff for sure in Cocoa world. But here is some flow which should help. Open your ImageCollectionViewItem.xib in Interface Builder and drag "Collection View Item" from Object Library, then select it and set your custom class name to ImageCollectionViewItem, then makeItemWithIdentifier should create non-nil item.

    In my example I have Tile class:

     class Tile: NSCollectionViewItem {
    

    And here is how I create the tiles:

    func collectionView(collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
    
        return items.count
    }
    
    
    func collectionView(collectionView: NSCollectionView,
                        itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem {
    
        let item = collectionView.makeItemWithIdentifier("Tile", forIndexPath: indexPath) as! Tile
        return item
    
    
    }
    

    Here is the picture of IB:

    enter image description here

    If you follow these steps, your outlets will be connected upon creation. In my case I have 2 outlets:

    class Tile: NSCollectionViewItem {
    
    @IBOutlet weak var bigScrollView: ItemScrollView!
    @IBOutlet weak var smallScrollView: ItemScrollView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override func viewDidAppear() {
        //
    }
    
    }
    

    And they are both get connected as you can see on the picture:

    enter image description here