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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to