Question

I don't know if what I see with a popup button populated by bindings with a value transformer is the way it's supposed to be or not -- the unusual thing I'm seeing (at least with respect to what I've seen with value transformers and table views) is that the "value" parameter in the transformedValue: method is the whole array bound to the array controller, not the individual strings in the array. When I've done this with table views, the transformer is called once for each displayed row in the table, and the "value" parameter is whatever object is bound to that row and column, not the whole array that serves as the content array for the array controller.

I have a very simple app to test this. In the app delegate there is this:

+(void)initialize {
    RDTransformer *transformer = [[RDTransformer alloc] init];
    [NSValueTransformer setValueTransformer:transformer forName:@"testTransformer"];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.theData = @[@{@"name":@"William", @"age":@"24"},@{@"name":@"Thomas", @"age":@"23"},@{@"name":@"Alexander", @"age":@"64"},@{@"name":@"James", @"age":@"47"}];
}

In the RDTransformer class is this:

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


+(BOOL)allowsReverseTransformation {
    return NO;
}

-(id)transformedValue:(id)value {
    NSLog(@"%@",value);
    return value;
}

In IB, I added an NSPopupButton to the window and an array controller to the objects list. The content array of the controller is bound to App Delegate.theData, and the Content Values of the popup button is bound to Array Controller.arrangedObjects.name with the value transformer, testTransformer.

When I run the program, the log from the transformedValue: method is this:

2012-09-19 20:31:39.975 PopupBindingWithTransformer[793:303] (
)
2012-09-19 20:31:40.019 PopupBindingWithTransformer[793:303] (
    William,
    Thomas,
    Alexander,
    James
)

This doesn't seem to be other people's experience from what I can see on SO. Is there something I'm doing wrong with either the bindings or the value transformer?

Was it helpful?

Solution

Unfortunately, this is how NSPopUpButton works. The problem is not limited to that control. If you try binding an NSArrayController.contentArray to another NSArrayControllers.arrangedObject.someProperty you will get the same problem. Here is a simple workaround that I use in all my value transformers, which makes them work with both tables and popups:

You can modify your value transformer in the following way:

-(id)transformedArrayValue:(NSArray*)array
{
    NSMutableArray *result = [NSMutableArray array];
    for (id value in array)
        [result addObject:[self transformedValue:value]];

    return result;
}

-(id)transformedValue:(id)value
{
    if ([value isKindOfClass:[NSArray class]])
        return [self transformedArrayValue:value];

    // Do your normal-case transform...
    return [value lowercaseString];
}

It's not perfect but it's easy to replicate. I actually put the transformedArrayValue: in a class category so that I don't need to copy it everywhere.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top