Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C bindings - Binding an enum to an NSPopupButton

I'm working on a project which would be ideally suit Cocoa bindings for the UI but I'm having an issue binding the value of an object property and can't find a suitable solution. The object is as follows:

typedef enum tagCSQuality {
    kQualityBest            = 0,
    kQualityWorst           = 1
} CSQuality;

@interface CSProfile : NSObject {
   NSString *identifier;
   NSString *name;
   CSQuality quality;
}

In the XIB, I have an object controller whose content object is bound to a "currentSelection" property of the window controller which is an instance of the above object. I've then bound the name and identifier which all work as expected but I cannot see how I can bind the enums.

Ideally I would like an NSPopupButton to display "Best" and "Worst" and pick the correct enum value. I have updated the enum to have an explicit numeric value and I believe that I need a value transformer to convert the values but I'm stuck on exactly how this could be implemented.

Can anyone help me out or point me in the right direction?

Thanks, J

like image 410
JWood Avatar asked Aug 22 '11 11:08

JWood


3 Answers

You can use an NSValueTransformerfor this.

Since the enumeration values are integers only, they are encapsulated in an NSNumber object.

An valid transformer could look like the following.

+(Class)transformedValueClass {
    return [NSString class];
}

-(id)transformedValue:(id)value {
    CSQuality quality = [value intValue];
    if (quality == kQualityBest)
        return @"Best";
    else if (quality == kQualityWorst)
        return @"Worst";

    return nil;
}

This can be bound to the Selected Value binding of the NSPopupButton.

If you want to create a bidirectional binding (i.e. be able to select something in the NSPopupButton you have to add the following code for the reverse transformation:

+(BOOL)allowsReverseTransformation {
    return YES;
}

-(id)reverseTransformedValue:(id)value {
    if ([@"Worst" isEqualToString:value]) 
        return [NSNumber numberWithInt: kQualityWorst];
    else if ([@"Best" isEqualToString:value]) 
        return [NSNumber numberWithInt: kQualityBest];

    return nil;
}
like image 50
Sebastian Avatar answered Oct 22 '22 08:10

Sebastian


An enum is not an object. Cocoa bindings are a way to connect model objects to view objects.

like image 41
NSResponder Avatar answered Oct 22 '22 09:10

NSResponder


If you are using Interface Builder, you can embed enum represented integer for each NSMenuItem items through property panel. Then select NSPopUpButton and specify binding 'selected tag' to the property with key path.

In this example, assume, IB's file owner is CSProfile. Prepare NSPopUpButton with two NSMenuItem items and tag them with 0(kQualityBest) and 1(kQualityWorst). Then navigate 'selected tag' of NSPopUpButton and check bind to 'File's owner'(CSProfile) with Model Key Path 'quality'.

@interface CSProfile : NSObject {
   NSString *identifier;
   NSString *name;
   CSQuality quality;
}
@property (assign) CSQuality quality;
like image 2
Kaz Yoshikawa Avatar answered Oct 22 '22 09:10

Kaz Yoshikawa