1

I am having a problem where it seems I am able to add items to a collection view, and have the prototype cells I created from a subclass of NSCollectionViewItem, but when I try to change the labels in order to display the data from the is get errors because they are nil, even though I connected them from the interface builder.

I also checked out the representedObject property by printing by attacked a mouseup function to the cell, and it was working fine. It only falls apart when I attempt to assign to the stringValue of the apparently nonexistent outlets.

Down below you can see my storyboard and the controller for the item views. The Label objects are represented down below as the two @IBOutlets. representedObject is being aliased as var morpheme : Morpheme? Storyboard view

Here in the main window controller I am testing out just adding the Morpheme objects to the collection with test values that I'm wanting to populate the Labels with. Main Window Code

The display shows the cells in a list, but when I click them it crashes due to a nil value from the apparently uninstantiated outlets. If you look in the console Morpheme 3 was printed successfully, so the data model made it in. Is there anything more I need to do? There is a lot of stuff about using the binding menu floating around, but I haven't played around much with it. Error display

Alexandstein
  • 76
  • 1
  • 7

1 Answers1

2

That is very interesting problem which already gained a lot of traction. The problem seems to be a bug in Cocoa so when items created from prototype, their outlets dont get hooked.

Look what happens when prototype is created:

enter image description here

Then when actual instance is created the outlets are nil:

enter image description here

So my recommendation would be to use one of 2 solutions:

  1. Use nibs and NSCollectionViewDataSource to create collection view items based on Views. Look for the last answer here: Cocoa - Where is the link between a NSCollectionView and a NSCollectionViewItem? Xcode 6 Bug?

Or just see examples with keyword: "makeItemWithIdentifier"

  1. Dont use outlets and use data binding as I did in my example. I bound my text edit to represented object:

enter image description here

And here is my code in controller:

class ViewController: NSViewController {

dynamic var collectionViewData = [String]()

@IBOutlet weak var collectionView: NSCollectionView!

override func viewDidLoad() {
    super.viewDidLoad()

    guard let proto = self.storyboard?.instantiateControllerWithIdentifier("collectionViewItem") as? CustomCollectionViewItem else { return }

    collectionView.itemPrototype = proto

    collectionViewData.append("One")
    collectionViewData.append("Two")
}

My final picture is (you can see I bound label to the actaul string in the array):

enter image description here

Community
  • 1
  • 1
Eugene Mankovski
  • 1,180
  • 10
  • 16
  • Thanks! This helped with the initial binding issue. Now it seems I still have some issues in that the list is still showing up blank, and I found out this is because when the cells try to display their data (a `Morpheme?` object) isn't set up so they're turning up `nil`. Later when I click on them I can get them to print to the console but the labels don't update when the representative object is finally available. – Alexandstein Jun 29 '16 at 03:51
  • 1
    For binding system to track changes you have to either use dynamic keyword: dynamic var morpheme: Morpheme? or if there is an explicit setter you should let them know calling pre/post KVC functions: willChangeValueForKey("morpheme") representedObject = newValue didChangeValueForKey("morpheme") Same story for any enclosed properties inside Morpheme object (if you have bound something to them) – Eugene Mankovski Jun 29 '16 at 11:51
  • Looks like it worked. Thanks! It looks like one minor detail I got wrong was using `viewWillAppear()` instead of `viewDidLoad()`. I wasn't sure what the firing order was, which led to the binding synchrony issues. – Alexandstein Jun 30 '16 at 07:06