0
votes

I have a problem with a bound property of a custom view. The property is bound to an NSArrayController for a core-data entity.

Here's the problem:

In my view, I draw several rectangles. The positions of these rectangles are saved in an entity in core data (as NSValue wrapped NSRects). The rectangles are draggable, and when I drag a rectangle, I want the entity to be updated to the new position. But I can’t find out how to bind the arrayController back to the view.

Here is how everything is connected:

  • I have a windowController with outlets to the view and the arrayController.

  • The arrayController is bound to the managedObjectContext of the windowController and therefore to my core-data model. (That binding and the binding to the entity are established in Interface Builder)

  • The view is bound to the arrayController with an ivar „rectangleValuesArray“

That last binding is established in the windowController using:

[connectionsView bind:@"rectangleValuesArray"
             toObject:elementsArrayController
          withKeyPath:@"arrangedObjects.rectangleValue"
              options:nil];

That works so far.

Now I tried to establish the binding in the other direction with:

[elementsArrayController bind:@"arrangedObjects.rectangleValue"
                     toObject:connectionsView
                  withKeyPath:@"rectangleValuesArray"
                      options:nil];

Now when I change my ivar, the Entity should be updated (right?). But that doesn’t work - I get that from the console:

Cocoa Bindings: Error setting value for bound property arrangedObjects.rectangleValue of object <NSArrayController: 0x200027100>[entity: Element, number of selected objects: 1]: [<NSArrayController 0x200027100> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key arrangedObjects.rectangleValue.

What am I getting wrong here? Please, somebody help?

Simon

2

2 Answers

2
votes

A couple of things.

First, the exception is correct: It isn't possible to set the rectangle value of any NSValue objects. They're immutable.

It sounds like you're trying to maintain parallel arrays, with the array of rectangles being one of them. Don't do that; Bindings chokes on it and it makes AppleScript support much harder as well.

What you need to do is implement model objects, and keep a single array of those. Whatever arrays you currently have, including the one of rectangles, should become properties of the model objects—each one has a rectangle, among whatever other things.

The other thing is that you don't bind the controller to the view; you bind the view to the controller. Having already done that, you're done.

You might also consider setting this up in IB instead of in code, if possible. Don't resist using IB; it is your friend.

0
votes

Not entirely sure I follow what you're doing there, but have you considered this approach:

  • give the view an IBOutlet NSArrayController* myArrayController ivar for your array controller (might already have something like that, I figure), and set up that connection in IB
  • omit your two manual binding calls from the window controller

Now in order to modify the contents of the array controller from within the view, you'd call [myArrayController mutableArrayValueForKeyPath:@"arrangedObjects.rectangleValue"], which should give you a proxy to that key path which you can modify at will with KVO updates.

Hope that's not entirely besides the point.