0

i've split up my UI into various nib files.

now, i use two nswindowcontroller subclasses with nsarraycontroller and nsobjectcontroller IBOutlets. The nwwindowcontrollers are the File's Owner in their respective nibs.

the controllers are assigned in IntefaceBuilder (IB).

previously in the one nib, i had a binding from an employees nsarraycontroller to a single employee nsobjectcontroller, using a controllerkey of 'selection' and modelkeypath of 'self'

now, i try to 'bind' them via code, as such

- (IBOutlet) showEmployeeWindow:(id)sender;

//load a window from a nib file.
    ...

// Get the employee arraycontroller.
NSArrayController *employeesController = [employeesWindowController employeeArrayController];  

// Get the selected employee from the employeeS controller
id employee = [empController selection]; 

//now the employee 
NSObjectController *emplController = [singleEmployeeWindowController employeeController];

//Set the content object of the employee controller as the nsset called employees.
[emplController setContent: employee]; 

//Show the window.
[singleEmployeeWindowController showWindow:sender];

    ...

}

The problem.

the debug does shows that a different memory address for the selected employee. ie, the line

id employee = [empController selection]; 
// Get the selected employee from the employeeS controller

seems to get a different employee.

but i consistently see the first employee never the selected one.

the selected employee is never set as the content -- or more precisely the selected employee doesnt replaces the default first one.

Note that each nswindowcontroller has a nsmanagedobject context set via the nsdocument. its the File's Owner in the nib.

Gabe Rainbow
  • 3,658
  • 4
  • 32
  • 42

1 Answers1

4

Isnt it often the case. after 2 days of pulling your hair out. ask a question and bang the answer comes within 1/2 hour.

So the secret is essentially cocoa bindings, and specifically Key Value Bindings

That documentation is the typical yackademic yadda yadda. The cascading clue actually came from a similar stack overflow question

So all one needs to do is link the two controllers together like this.

NSArrayController *source = [employeesWindowController employeeArrayController]];
NSObjectController *destination = [singleEmployeeWindowController employeeController];

[destination bind:@"contentObject" toObject:source withKeyPath:@"selection.self" options:nil];

The syntax follows that of the Interface Builder bindings.

Bind to: Content Object 
Content Key: selection
ModelKeyPath: self

So its a darn easy one liner.

Binding a NSLabel to a Controller. In IB

Bind to: Value 
Content Key: selection
ModelKeyPath: name

In code,

[label bind:@"value" toObject:controllerRef withKeyPath:@"selection.name" options:nil];

And the options mimic those of "Raises for Not Applicable Keys" and so forth. See yackademic text for the details.

bikram990
  • 1,085
  • 1
  • 14
  • 36
Gabe Rainbow
  • 3,658
  • 4
  • 32
  • 42
  • I was prepared to like this answer, but the code you give will not only give errors but is misleading to other developers. For instance @"selection.self" is wrong on more than one level. – Elise van Looij Mar 02 '17 at 11:12
  • Thanks! Just enough info to help me understand the purpose of each of the 'bind' arguments. – RichS Aug 30 '17 at 22:20
  • Thank you, binding to the keyPath "selection.self" instead of "selection" was the key for my case. Instead of "contentObject" I used the `NSContentBinding` constant in AppKit. – Andrew Sep 21 '17 at 20:04