NSPopupButton绑定与值变换器

rde*_*mar 4 macos objective-c cocoa-bindings nspopupbutton nsvaluetransformer

我不知道我用弹出式按钮填充的值是否与应变值绑定是否应该是它应该是不是 - 这是我看到的不寻常的事情(至少就我所看到的而言)值转换器和表视图)是transformedValue:方法中的"value"参数是绑定到数组控制器的整个数组,而不是数组中的单个字符串.当我使用表视图完成此操作时,变换器将为表中的每个显示行调用一次,"value"参数是绑定到该行和列的任何对象,而不是用作内容数组的整个数组对于阵列控制器.

我有一个非常简单的应用程序来测试它.在app委托中有这样的:

+(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"}];
}
Run Code Online (Sandbox Code Playgroud)

在RDTransformer类中是这样的:

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


+(BOOL)allowsReverseTransformation {
    return NO;
}

-(id)transformedValue:(id)value {
    NSLog(@"%@",value);
    return value;
}
Run Code Online (Sandbox Code Playgroud)

在IB中,我向窗口添加了一个NSPopupButton,并在对象列表中添加了一个数组控制器.控制器的内容数组绑定到App Delegate.theData,弹出按钮的内容值绑定到Array Controller.arrangedObjects.name,其值为transform,testTransformer.

当我运行程序时,来自transformedValue:方法的日志是这样的:

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

从我在SO上可以看到的情况来看,这似乎不是其他人的经验.对于绑定或值变换器,我有什么问题吗?

aLe*_*ion 7

不幸的是,这就是NSPopUpButton的工作原理.问题不仅限于该控制.如果您尝试将NSArrayController.contentArray绑定到另一个NSArrayControllers.arrangedObject.someProperty,您将遇到相同的问题.这是我在所有值变换器中使用的简单解决方法,这使得它们可以同时使用表和弹出窗口:

您可以通过以下方式修改值转换器:

-(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];
}
Run Code Online (Sandbox Code Playgroud)

它并不完美,但很容易复制.我实际上把它transformedArrayValue:放在一个类别中,这样我就不需要在任何地方复制它了.