Search code examples
cocoansdictionarycocoa-bindings

How can I bind to values of NSDictionary sub-dictionaries in Cocoa?


I've a class with two properties: NSString *fileName, and NSDictionary *frames illustrated below.

  • NSDictionary *frames
    • key: NSString
    • value: instance of fields dictionary
  • NSDictionary *fields
    • key: NSNumber (C++ enum value)
    • value: NSValue (C++ object pointer)

I want to create a master-detail view with an NSTableView listing each file. fileName in the first column, which is easy enough to bind, but I can't figure out how to bind any columns, nor fields in the detail view, to values in the fields sub-dictionaries.

I guess I can't bind to C++ object methods anyway. I'm thinking I need a custom controller for the value in the fields sub-dictionary. Would it be possible to have the custom controller adhere to KVC such that I can access field values by enum key, calling methods appropriate to the type defined by the enum per the C++ library I'm using?

Or, should I store the data from each field as the value in the fields dictionary? After modifying the value in the GUI, I'd have to run a method to process the dictionaries anyway, at which point I can reconstruct the C++ fields object and call the appropriate methods.

Regardless, my challenge is figuring out bindings for a nested dictionary.


Solution

  • I ended up storing the data for each field as the value in the "fields" sub-dictionary. I didn't realize I could specify a key-path to bind to the value.

    For example, I have a class with a member NSArray "tracks" containing a set of objects each with member NSDictionary "frames" as described in my question. "tracks" is represented in my GUI with an NSArrayController to which is bound an NSTableView.

    Within the NSTableView I can bind the static text of the table cells to the Table Cell View with model key path "objectValue.frames.key1.key2".

    Likewise, within the detail part of the master-detail view, I can bind text field cells to the NSArrayController with "selection" as controller key, and "frames.key1.key2" as model key path.