1

I have been reading tutorials online and the Apple docs, but as someone new to writing Cocoa apps (25 years of embedded C/C++ firmware & networking code), this dark art of Cocoa bindings makes no sense to me.

1) I created a document based MacOS Cocoa app in XCode.

2) In it, I created a class called DocumentData, subclass of NSObject.

3) In DocumentData are "foo" and "bar", two "dynamic" properties that are both Strings.

4) My Document subclass of NSDocument contains a DocumentData property called docData.

5) In the makeWindowControllers() method of my Document class, I set the represented object of the viewController to be its docData property by adding the following, after self.addWindowController(windowController):

if let viewController = windowController.contentViewController as! ViewController? { viewController.representedObject = self.docData }

6) In the View Controller Scene I added two NSTextFields to the View Controller View and called them "Foo" and "Bar" respectively.

7) I used the Assistant to ctrl drag them to the View Controller swift code window to create two IBOutlets in the View Controller, called "foo" and "bar" respectively.

8) In the read() method of my Document class, I added two lines of code to set the two properties of the docData object:

   docData.foo = "foo"
   docData.bar = "bar"

At this point, I think if I can get Cocoa binding set up correctly, when I open a document which has my app's file extension using "Open" from the app's "File" menu, I think a window should come up whose title is set to the name of the file I selected and where the two NSTextField objects in the window say "foo" and "bar" respectively.

The problem is, I'm completely confused on how to do those bindings. I've seen ten different examples with different ways of doing the bindings, but nothing seems to work for me.

Am I supposed to add an NSArrayController to the View Controller?

Am I supposed to add an NSObjectController to the View Controller?

How exactly, in XCode's ridiculously confusing UI, am I supposed to set up exactly what bindings?

I'm sure this probably very simple to do, but I don't get it. Any help or any pointer to an online tutorial that doesn't assume far more experience with the XCode IDE than those I've found online thus far would be most appreciated.

When this works for me, I'm happy to put the code up on github somewhere and comment the heck out of it to help others struggle with XCode's nefarious IDE as it relates to these bindings.

1 Answers1

1

Steps 1-6 are all good. Step 7 is not necessary for bindings but you may need this for your app anyway. Step 8 is all good.

I seems that all you are missing is to bind the NSTextFields to your view controller.

You can bind them directly to your view controller without using NSObjectController or NSArrayController.

In Interface Builder, in the bindings inspector tab on the right side you will bind the value property to foo and bar.

Bind to will be checked and your view controller selected.

Controller Key will be empty and Model Key Path will be self.representedObject.foo or self.representedObject.bar depending on the text field you are binding.

For more information on available bindings take a look at the bindings documentation for NSTextField here.

For more on the "dark arts" of correct bindings look at the example project I linked in my answer here.

A.C. Wright
  • 921
  • 9
  • 21
  • I tried this last night (literally my 2nd day ever in XCode) and I was getting an exception thrown in the debugger output, so I thought I must have been doing something wrong and went all over the web looking for other ways to do the binding. Did it your way & got the exception again. But just I tracked that down to the fact that the default doc-based app overrides `representedObject` in the `ViewController` template Apple starts you with. I took out the call to `override var representedObject: Any?` and now it works! Thanks so much for your help. – Pointy-Haired Boss Oct 11 '17 at 05:48
  • Glad I could help! – A.C. Wright Oct 11 '17 at 06:46
  • 1
    Bind a `NSTextField` to a subclass of `NSController` if it is editable. It works better. `NSController` implements the `NSEditor` and `NSEditorRegistration` informal protocols. [Why Are NSControllers Useful?](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/WhatAreBindings.html#//apple_ref/doc/uid/20002372-177085) – Willeke Oct 11 '17 at 12:13