Search code examples
objective-ccocoadata-bindingappkit

How do I neatly bind Cocoa inputs to NSDocument properties?


Let's say I have a simple NSDocument subclass:

@interface Document : NSDocument
@property NSString *someText;
@end

I want to map someText to some field in my view - so I add a new field to my view controller:

@interface ViewController : NSViewController
@property Document* document;
@end

...and make sure to store my document:

- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];
    self.document = ((Document*)representedObject);    
}

Oh yeah, and I make sure that the document property is dynamic, which a bit of googling brought up as important for data binding:

@implementation Document
@dynamic someText;
@end

Then head on over to my NSTextField and try to bind the value:

A screenshot of XCode binding interface failing to recognize a Model Key Path

As you can see, it reports that "Xcode cannot resolve the entered keypath." Furthermore, the "Controller Key" field (which I believe is where I'm supposed to specify document, with self.someText for the keypath?) is entirely greyed out.

What am I doing wrong?


Solution

  • It turns out that @dynamic isn't necessary - what is necessary is that the view controller's representedObject is set quite early.

    I modified the default generated makeWindowControllers in the Document class so that it sets representedObject on the just-created WindowController's contentViewController before addWindowController is invoked:

    - (void)makeWindowControllers {        
        NSWindowController *wc = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Document Window Controller"];
        wc.contentViewController.representedObject = self;
        [self addWindowController:wc];    
    }
    

    And then, in my storyboard, I simply bound to View Controller with a Model Key Path of representedObject.someText. (Be sure to check off "Continuously Updates Value" if things still don't seem to be changing - otherwise the data model might only be updated on certain events such as focus change.)