Re: Bidirectional, Manual Binding in custom control
Re: Bidirectional, Manual Binding in custom control
- Subject: Re: Bidirectional, Manual Binding in custom control
- From: Quincey Morris <email@hidden>
- Date: Mon, 21 May 2012 21:52:14 -0700
On May 21, 2012, at 20:44 , Jerry Krinock wrote:
> and then binding to it in the window controller's -awakeFromNib like this…
> [starRatingView bind:@"rating"
> toObject:fooController
> withKeyPath:@"selection.rating"
> options:beForgiving] ;
> -(void)setRating:(float)rating
> {
> // Stuff to make reverse binding work…
> NSDictionary* bindingsInfo = [self infoForBinding:@"rating"] ;
> id object = [bindingsInfo objectForKey:NSObservedObjectKey] ;
> NSString* bindingsPath = [bindingsInfo objectForKey:NSObservedKeyPathKey] ;
> [object setValue:[NSNumber numberWithFloat:rating]
> forKeyPath:bindingsPath] ;
>
> // Set ivar, needsDisplay
> …
> }
>
> This all makes sense, and it works. But it seems awkward. Is there a better design pattern?
This seems more or less the correct approach to defining a custom binding. "More or less" because you may have committed some minor technical violation of custom binding implementations, described unintelligibly in this document:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html
However, it's not particularly clear what benefit it brings you to implement a custom binding, since there's no practical way any more (AFAIK) to use custom bindings in IB.
With a code-based approach, it may be easier and clearer just to implement the two halves of the behavior directly:
(a) Have your window controller KVO-observe fooController.selection.rating, using an observation method like this:
- (void) observeValueForKeyPath: (NSString*) keyPath ofObject: (id) object change: (NSDictionary*) change context: (void*) context {
if (context != myContext) …
else if (object == fooController && [keyPath isEqualToString: @"selection.rating"]) {
NSNumber* rating = [fooController valueForKeyPath: @"selection.rating"];
if ([rating isKindOfClass: [NSNumber class]])
starRatingView.objectValue = rating;
else
… // disable the control or whatever you want to do for not-applicable markers
}
else …
}
(b) Connect the Star Rating control to an action method that's implemented in the window controller:
(IBAction) changeRating: (sender) {
fooController.selection.rating = sender.floatValue;
}
(You could even do this entirely within the control itself, provided that the window controller configured it with an object and key path to observe, or it had some other way of finding what to observe.)
It's not so much a question of number of lines of code. It's rather that doing this without bindings seems much more obvious.
_______________________________________________
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