2010-07-18 20 views
2

Cocoa是否提供了一个内置的方法来将密钥字符串转换为正确格式的属性访问器?即"lineSpacing" -> setLineSpacing:Cocoa是否提供了一个内置的方法来将密钥转换为'set'属性访问器?

例如:

NSString * key = @"lineSpacing"; 
SEL selector = [key magicallyConvertIntoSetPropertyAccessor]; 

甚至:

NSString * key = @"lineSpacing"; 
SEL selector = NSSelectorFromString([key toSetPropertyAccessor]); 

背景:

我工作,将设置了许多特性的方法,通过名称,使用存储在字典中的属性值。我不能使用setObject:forKey,因为我也使用这种方法的内置类型的属性,如NSIntegerCGFloat。这是我使用CGFloat的方法的一个例子,来说明:

- (void)setFloatProperty:(NSString *)key value:(CGFloat)value target:(id)object 
{ 
    NSString * setPropertyString = [NSString stringWithFormat:@"set%@", 
            [key capitalizedString]]; 
    SEL selector = NSSelectorFromString(setPropertyString); 

    NSMethodSignature * signature = ... 
    NSInvocation * invocation = ... 

    CGFloat arg = value; 
    void * argument = &arg; 

    [invocation setArgument:argument atIndex:2]; 
    [invocation invoke]; 
} 

此方法适用于像“颜色”或“宽度”一个字的属性,但是未能在多功能使用词的属性,如“lineSpacing”或“meaningOfLifeTheUniverseAndEverything”,因为capitalize方法将首字母大写,而将所有后续字母设置为小写。呼叫使用“lineSpacing”作为失败的关键结果上面的方法,因为正确的属性setter会setLineSpacing:而不是setLinespacing:

回答

5

您正在寻找setValue:forKey:,这不仅能找到正确的二传手选择,但是发送消息您。它是the Key-Value Coding protocol的一部分;请注意,由于这个原因,像myProperty这样的获取者和setMyProperty:这样的设置者被称为“键值编码兼容”。

我正在使用存储在字典中的属性值按名称设置一些属性的方法。

另请参阅the setValuesForKeysWithDictionary: method,也是KVC协议的一部分。

+0

啊,对不起,我应该更具体。这适用于对象样式属性,但不适用于基元类型。我发布了我的setProperty方法的简化版本,但实际使用的是'NSInvocation',它需要更复杂的设置。我会改变我的问题来说清楚。 – 2010-07-18 03:05:48

+1

@ e.James它可以处理基元:http://pastie.org/1049035 – 2010-07-18 03:24:40

+0

e.James:为什么不只是实现你的'setFloatProperty:forKey:target:'方法来填充值并将其传递给'setValue :forKey:'?这会比尝试复制KVC的算法简单得多。 (如果您担心性能,请记住他们对过早优化的看法,您应该先以更简单的方式进行操作,然后对其进行配置,看看它是否让您陷入困境。) – 2010-07-18 03:26:09

1

苹果并没有作出面向公众的功能,要做到这一点,但总的算法很简单:

SEL SetterSelectorForKey(NSString *key) { 
    SEL result = 0; 

    NSString *strFirstCharacter = [[key substringToIndex: 1] uppercaseString]; 
    NSString *strRemainder = [key substringFromIndex: 1]; 

    result = NSSelectorFromString([NSString stringWithFormat: @"set%@%@:", strFirstCharacter, strRemainder]); 

    return result; 
} 

你去使用此之前,但是,请记住,有可能是其他途径完成你的目标。调查您使用的现有API,然后执行此操作(我可以补充说,如果@property的访问器设置为不同的内容,而不是可以正常工作。 Objective-C运行时,它会让你得到一个@property的设置。)

+1

尽管这一般起作用,你可以使用属性语法指定一个自定义setter名称:@property(setter = setMyFoo:,getter = isMyFoo)BOOL foo;'。 'setValue:forKey:'会知道这是最好的方法。 – 2010-07-18 03:27:04

+0

是的,因此我的警告。 :) – 2010-07-18 03:29:34

相关问题