Search code examples
objective-ccocoanstableviewnsarraycontroller

Binding an NSTableView to an NSArrayController instead of fetching the data directly from my model array


Current Situation: Direct Binding

I have an NSTableView which displays the data that comes from an NSArray of my custom objects.

Desired Approach: Array Controller

However, It would be "more best practise" to use an NSArrayController instead as a facade to my arbritary model object.

So I duplicated the table in my application and created a new NSViewController where I bound the Table Content of the NSTableView to the NSArrayController. I added an IBOutlet for this class so I can now setup my View Controller like this:

ContactListViewController *myVC = [[ContactListViewController alloc] init];

// Tell the ArrayController where the content-array is.
myVC.contactsArrayController.content = self.myModel.contactsArray;

Now since I bound the Table Content of the table view to the array controller, I would expect, that as soon as I fill the array with data (from a remote service) that the tableview is updated, which is the case for my other approach where I bind to myModel.contactsArray directly.

The Problem: No data

However, the table remains empty. Do I have to setup something else for this to work (Maybe some willChangeValueForKey-magic or something else I have missed. I already tried to set the array controller as the dataSource and the delegate of the NSTableView but that did not seem to work either (Anyway it is not clear to me how dataSource and the Table Content binding "relate to each other").


Solution

  • When you fill up your array with content, are you re-assigning an immutable array or appending to a mutable array? Either way, it won't work quite how you're expecting.

    When you set the content of an array controller this way, instead of keeping a reference, the array controller just copies the content. Subsequent changes will have no effect, whether it's a mutable array (nor if you reassign the model's contactsArray).

    Instead:

    1. Call -add:on the array controller when you insert content. That probably that won't help in your case.

    2. If you use immutable arrays you could bind the array controller to myModel's contactsArray key instead of assigning it.

    3. If you use a mutable array I don't think that will work. You could create a second array controller in the model and bound the view's array controller to contactsArrayController.arrangedObjects. Maybe there's a better way, but that's what I've done in the past.