I'm building an OS X app that uses core data, NSDocument, storyboards, and Cocoa bindings.
My expectation is that the following occurs:
An instance of MyDocument
(NSDocument
subclass) is created.
MyDocument
creates a Core Data NSManagedObjectContext
that represents the document's data.
MyDocument
instantiates an NSWindowController
from the storyboard by its identifier.
Within the storyboard, the window controller contains DocumentEditorViewController
(NSViewController
subclass) which displays and edits the document.
Within the storyboard, DocumentEditorViewController
has an NSArrayController
that's bound to MyDocument
's managed object context.
Within the storyboard, DocumentEditorViewController
has a table view that's bound to the NSArrayController
.
This way any changes in the UI make it all the way to the NSManagedObjectContext
, without any glue code.
I expect this to be straightforward, as I believe I'm using these technologies in the way they are intended. However I have been unable to get the bindings to work, particularly at steps 5 and 6. All of the project templates and example projects I've found either don't use Core Data, don't use storyboards, or don't use NSDocuments.
Which objects should be bound to which? What should teh NSArrayController's class, keys and keypath be?
Another way to answer this question is to point out a working sample project that uses all these technologies together.
Steps to create a sample Xcode Document-Based Application project with Core Data, Storyboard, NSArrayController, NSTableView and Bindings.
Step 1 Create a Xcode project. Choose OS X Cocoa Application and select ‘Use Storyboards’, ‘Create Document-Based Application’ and ‘Use Core Data’.
Step 2 Select the data model. Add entity ‘Person’ and string attributes ‘name’ and ‘address’.
Step 3 Select Main.storyboard. Add a NSArrayController to the view controller scene. Set Mode to ‘Entity Name’ and set Entity Name to ‘Person’. Check ‘Prepares Content’. Bind Managed Object Context
of the array controller to View Controller
, Model Key Path representedObject.managedObjectContext
.
Step 4 Go to the view of the view controller scene. Remove ‘Your document contents here’. Add a NSTableView. Bind Content
to Array Controller
, Controller Key arrangedObjects
. Bind Selection Indexes
to Array Controller
, Controller Key selectionIndexes
. Bind Sort Descriptors
to Array Controller
, Controller Key sortDescriptors
.
Step 5 Bind Value
of the text fields in the table view to Table Cell View
, Model Key Path objectValue.name
and objectValue.address
. Check 'Conditionally Sets Editable'.
Step 6 Add two Push Buttons ‘Add’ and ‘Remove’ to the view of the view controller scene. Connect the actions to actions add:
and remove:
of the array controller.
Step 7 (Objective-C) Select Document.h. In method makeWindowControllers
, replace statement [self addWindowController:…
by
NSWindowController *aWindowController = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Document Window Controller"];
[self addWindowController:aWindowController];
aWindowController.contentViewController.representedObject = aWindowController.document;
Step 7 (Swift) Select Document.swift. In method makeWindowControllers
, at the end after self.addWindowController(windowController)
add
windowController.contentViewController!.representedObject = windowController.document
Step 8 Build, Run, Test.