FROM : Ron Lue-Sang
DATE : Mon Jun 30 23:43:38 2008
Sorry, I haven't read every message in this thread, but I think I can
answer the original question
> [[self bar] bind:@"title" toObject:ivar_controller
> withKeyPath:@"selection.displayName" options:nil];
>
> Now here's the thing: if I call setDisplayName: on Foo, it calls
> Bar's setTitle: method, exactly as it should. However, if I call
> setTitle: on Bar, it does *not* end up calling Foo's setDisplayName:
> method, although it seems like it should. I can change the
> bind:toObject:withKeyPath:options: invocation above so that it binds
> Bar directly to Foo without going through the object controller, or
> I can try going the other way and binding the Foo to the Bar -
> always I get the same result.
Bindings of this type are one way. Their kinda ad hoc. "Title" will be
updated to match ivar_controller.selection.displayName. Changing title
will not result in any KVC calls to change anything in the
ivar_controller. This is a read-only setup.
It sounds like you're asking for 2 things.
1) To have logic that will update ivarController.selection.displayName
to match "title".
2) To have the logic from #1 triggered when setTitle is called.
There was some suggestion about using infoForBinding: to do blah blah
blah.
Yes! infoForBinding is what you should use to implement the logic in #1.
// in Bar get the infoForBinding dictionary
NSDictionary *info = [self infoForBinding:@"title"];
// extract the controller and keypath info
id controller = [info objectForKey:NSObservedObjectKey];
NSString *keyPath = [info objectForKey:NSObservedKeyPathKey];
// extra points for looking in the binding options for value
transformers and stuff
// options = [info objectForKey:NSOptionsKey];
// push/write the value to the controller
[controller setValue:theTitle forKeyPath:keyPath];
The trick to getting #2 is that setTitle is ALSO what gets called
during the regular we-did-the-read-work-for-you bindings update from
the controller. Don't let changing the displayName end up calling
setTitle if setTitle's going to set the displayName. Make sense?
So how do we fix this issue?
2a) Don't use setTitle to trigger logic in #1. This is the approach I
normally suggest. Your views should push these changes down due to
user interaction, not programatic fiddling.
2b) Implement the "read" logic yourself by implementing bind:. This
means you'll need to cache the binding info yourself, start observing
the controller object, and react to the KVO notifications
appropriately. Don't call super for bind:/unbind:/infoForBinding:
@"title".
As a final note - I'm not sure if anyone else mentioned it. The
original code snippets had stuff like
- (void)setTitle:(NSString *)title {
[self willChangeValueForKey:@"title"];
NSLog(@"setting title to %@", title);
if(title != ivar_title) {
[ivar_title release];
ivar_title = [title copy];
}
[self didChangeValueForKey:@"title"];
}
You don't need the will/did changeValueForKey:@"title" calls in the
setTitle: method if you haven't disabled automatic KVO notifications
for title. If you didn't know you could do that, then you haven't
disabled KVO notifications for your class and, therefore, don't need
to call will/did changeValueForKey:@"title".
Hope that clears things up.
On Jun 30, 2008, at 2:04 PM, Hamish Allan wrote:
> On Mon, Jun 30, 2008 at 3:56 PM, Michael Ash <michael.<email_removed>>
> wrote:
>
>> Although Apple's sample code shows overriding -bind:... to store
>> information about the new binding, it doesn't look like this is
>> necessary. You can simply use -infoForBinding: to obtain the info
>> dictionary, extract the bound object and key, and use that
>> information
>> to update the model object. I'd assume this is what the Apple classes
>> do, and it seems to me to be a lot simpler than overriding -bind:...
>> to stash away a bunch of information that's already being stored for
>> you anyway.
>
> That would seem a pretty reasonable assumption, but it doesn't seem to
> be the case. At least, breakpoints on -[NSTextField infoForBinding:],
> -[NSControl infoForBinding:], -[NSObject infoForBinding:] don't seem
> to trigger when the text field is edited; nor are messages logged from
> a subclass of NSTextField overriding -infoForBinding:.
>
> Any other ideas, anyone?
>
> Thanks,
> Hamish
> _______________________________________________
>
> Cocoa-dev mailing list (<email_removed>)
>
> 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:
> http://lists.apple.com/mailman/options/cocoa-dev/<email_removed>
>
> This email sent to <email_removed>
--------------------------
RONZILLA
DATE : Mon Jun 30 23:43:38 2008
Sorry, I haven't read every message in this thread, but I think I can
answer the original question
> [[self bar] bind:@"title" toObject:ivar_controller
> withKeyPath:@"selection.displayName" options:nil];
>
> Now here's the thing: if I call setDisplayName: on Foo, it calls
> Bar's setTitle: method, exactly as it should. However, if I call
> setTitle: on Bar, it does *not* end up calling Foo's setDisplayName:
> method, although it seems like it should. I can change the
> bind:toObject:withKeyPath:options: invocation above so that it binds
> Bar directly to Foo without going through the object controller, or
> I can try going the other way and binding the Foo to the Bar -
> always I get the same result.
Bindings of this type are one way. Their kinda ad hoc. "Title" will be
updated to match ivar_controller.selection.displayName. Changing title
will not result in any KVC calls to change anything in the
ivar_controller. This is a read-only setup.
It sounds like you're asking for 2 things.
1) To have logic that will update ivarController.selection.displayName
to match "title".
2) To have the logic from #1 triggered when setTitle is called.
There was some suggestion about using infoForBinding: to do blah blah
blah.
Yes! infoForBinding is what you should use to implement the logic in #1.
// in Bar get the infoForBinding dictionary
NSDictionary *info = [self infoForBinding:@"title"];
// extract the controller and keypath info
id controller = [info objectForKey:NSObservedObjectKey];
NSString *keyPath = [info objectForKey:NSObservedKeyPathKey];
// extra points for looking in the binding options for value
transformers and stuff
// options = [info objectForKey:NSOptionsKey];
// push/write the value to the controller
[controller setValue:theTitle forKeyPath:keyPath];
The trick to getting #2 is that setTitle is ALSO what gets called
during the regular we-did-the-read-work-for-you bindings update from
the controller. Don't let changing the displayName end up calling
setTitle if setTitle's going to set the displayName. Make sense?
So how do we fix this issue?
2a) Don't use setTitle to trigger logic in #1. This is the approach I
normally suggest. Your views should push these changes down due to
user interaction, not programatic fiddling.
2b) Implement the "read" logic yourself by implementing bind:. This
means you'll need to cache the binding info yourself, start observing
the controller object, and react to the KVO notifications
appropriately. Don't call super for bind:/unbind:/infoForBinding:
@"title".
As a final note - I'm not sure if anyone else mentioned it. The
original code snippets had stuff like
- (void)setTitle:(NSString *)title {
[self willChangeValueForKey:@"title"];
NSLog(@"setting title to %@", title);
if(title != ivar_title) {
[ivar_title release];
ivar_title = [title copy];
}
[self didChangeValueForKey:@"title"];
}
You don't need the will/did changeValueForKey:@"title" calls in the
setTitle: method if you haven't disabled automatic KVO notifications
for title. If you didn't know you could do that, then you haven't
disabled KVO notifications for your class and, therefore, don't need
to call will/did changeValueForKey:@"title".
Hope that clears things up.
On Jun 30, 2008, at 2:04 PM, Hamish Allan wrote:
> On Mon, Jun 30, 2008 at 3:56 PM, Michael Ash <michael.<email_removed>>
> wrote:
>
>> Although Apple's sample code shows overriding -bind:... to store
>> information about the new binding, it doesn't look like this is
>> necessary. You can simply use -infoForBinding: to obtain the info
>> dictionary, extract the bound object and key, and use that
>> information
>> to update the model object. I'd assume this is what the Apple classes
>> do, and it seems to me to be a lot simpler than overriding -bind:...
>> to stash away a bunch of information that's already being stored for
>> you anyway.
>
> That would seem a pretty reasonable assumption, but it doesn't seem to
> be the case. At least, breakpoints on -[NSTextField infoForBinding:],
> -[NSControl infoForBinding:], -[NSObject infoForBinding:] don't seem
> to trigger when the text field is edited; nor are messages logged from
> a subclass of NSTextField overriding -infoForBinding:.
>
> Any other ideas, anyone?
>
> Thanks,
> Hamish
> _______________________________________________
>
> Cocoa-dev mailing list (<email_removed>)
>
> 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:
> http://lists.apple.com/mailman/options/cocoa-dev/<email_removed>
>
> This email sent to <email_removed>
--------------------------
RONZILLA






Cocoa mail archive

