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:
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?
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.)