• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Trouble binding against transient Core Data property
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Trouble binding against transient Core Data property


  • Subject: Re: Trouble binding against transient Core Data property
  • From: Quincey Morris <email@hidden>
  • Date: Sun, 10 Oct 2010 22:31:47 -0700

On Oct 10, 2010, at 21:52, Rick Mann wrote:

> @dynamic shadowFrame;
>
> "frame" is a transient Core Data property of Undefined Type, but it's an NSRect in the class file. Its implementation:
>
> - (NSRect)
> frame
> {
> 	[self willAccessValueForKey:@"frame"];
> 	NSString* v = self.shadowFrame;
> 	[self didAccessValueForKey:@"frame"];
> 	NSRect nsR = NSRectFromString(v);
> 	return nsR;
> }

The Core Data programming guide is a bit hard to follow on this subject (because it talks about the difficult cases and not the easy cases), but I *think* this is an unnecessary approach. Just don't put "frame" in the Core Data model at all, and let it be a regular property. The implementation is the same as you've got, except that you don't need the willAccess/didAccess/wiilChange/didChange calls. OTOH, I *think* what you did should work fine. I'm pretty sure this is nothing to do with your problem.

On Oct 10, 2010, at 21:52, Rick Mann wrote:

> 	VisualizationPlugIn* vp = ...;
> 	NSView* view = vp.displayViewController.view;
> 	[vp bind: @"frame" toObject: view withKeyPath: @"frame" options: nil];
>
> I may not really fully understand bindings, in the sense that I don't know what you mean about NSView not having a "frame" binding. The docs imply that you can only call -bind:... on a binding that you've called -exposeBinding:... on, but someone at Apple told me that you only need to call -exposeBinding:... for IB's sake.


It's more complicated than that. 'exposeBinding...' is necessary only for IB's sake, so it's basically irrelevant to this discussion.

However, a binding -- a real, honest-to-goodness Cocoa binding -- needs support code in the class that defines the binding. This support code essentially makes sure that the bound object are updated in both directions. For *one* of the directions (from the bound object to the bound-to object), the standard implementation of 'bind:toObject:withKeyPath:options:' in NSObject is normally perfectly adequate. The other direction is custom code in the class providing the binding.

So, when I said NSView doesn't have a "frame" binding, I meant it doesn't have this custom code for a binding named "frame". (It does have the code for a binding named "toolTip", for example.)

Under these circumstances, when you call [object1 bind:@"xyz" toObject: object2 withKeyPath:@"abc" options:...], all you get is object1's KVC-compliant property "xyz" following object2's "abc" property, but not vice versa. In that sense, this is not about bindings at all -- 'bind...' serves merely as a convenient way to set up a uni-directional KVO observance.

In your case, you reversed the order of the objects -- you "bound" the plugin's "frame" property to the view's "frame" property. In other words, you told your plugin object to KVO observe the view, and nothing more. That's why moving the view changes the model. But since it's uni-directional, changing the model (e.g. via undo) doesn't change the view.

If this sounds confusing, it is. The term "binding" is essentially ambiguous is very non-trivial way. That's why I strongly object to using 'bind...' for mere KVO observance -- it obscures the real operation of the bindings mechanism.

In summary, you've:

1. "bound" in the wrong direction -- you should have attempted to bind from the view to the data model (plugin)

2. failed to establish a "frame" binding because none of the classes involve has a "frame" binding (just a "frame" property, which is insufficient for your purposes)

3. set up a one-way KVO observance that provides precisely half the functionality you want

One way or another, you're going to have to come up with code to handle both directions of frame change: model-to-view  and view-to-model. One approach is to use KVO observance (via [view bind:@'frame" toObject:vp withKeyPath:@"frame" options:0] if you really want to -- note the change of direction) for one direction, and have a controller object (such as a view controller or window controller) observe frame-change notifications from the view and update the model property directly.

Or something like that.




_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Follow-Ups:
    • Re: Trouble binding against transient Core Data property
      • From: Rick Mann <email@hidden>
    • Re: Trouble binding against transient Core Data property
      • From: Rick Mann <email@hidden>
References: 
 >Trouble binding against transient Core Data property (From: Rick Mann <email@hidden>)
 >Re: Trouble binding against transient Core Data property (From: Quincey Morris <email@hidden>)
 >Re: Trouble binding against transient Core Data property (From: Rick Mann <email@hidden>)

  • Prev by Date: Re: Trouble binding against transient Core Data property
  • Next by Date: Re: Return value of performSelector:onThread:?
  • Previous by thread: Re: Trouble binding against transient Core Data property
  • Next by thread: Re: Trouble binding against transient Core Data property
  • Index(es):
    • Date
    • Thread