Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you bind a storyboard view to a Core Data entity when using NSDocument?

I'm building an OS X app that uses core data, NSDocument, storyboards, and Cocoa bindings.

My expectation is that the following occurs:

  1. An instance of MyDocument (NSDocument subclass) is created.

  2. MyDocument creates a Core Data NSManagedObjectContext that represents the document's data.

  3. MyDocument instantiates an NSWindowController from the storyboard by its identifier.

  4. Within the storyboard, the window controller contains DocumentEditorViewController (NSViewController subclass) which displays and edits the document.

  5. Within the storyboard, DocumentEditorViewController has an NSArrayController that's bound to MyDocument's managed object context.

  6. 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.

like image 436
Bob Whiteman Avatar asked Feb 03 '16 02:02

Bob Whiteman


1 Answers

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.

like image 120
Willeke Avatar answered Oct 20 '22 07:10

Willeke