Does Cocoa provide a built-in method to convert a key into a 'set' property accessor?
Does Cocoa provide a built-in method to convert a key string into a properly-formatted set property accessor? i.e. "lineSpacing" -> setLineSpacing:
For example:
NSString * key = @"lineSpacing";
SEL selector = [key magicallyConvertIntoSetPropertyAccessor];
or even:
NSString * key = @"lineSpacing";
SEL selector = NSSelectorFromString([key toSetPropertyAccessor]);
Background:
I'm working on a method that will set a number of properties, by name, using property values stored in a dictionary. I can't use setObject:forKey
because I also use this method for properties that are of built-in types like NSInteger
and CGFloat
. Here is an example of the method I use for CGFloat, to illustrate:
- (void)setFloatProperty:(NSString *)key value:(CGFloat)value target:(id)object
{
NSString * setPropertyString = [NSString stringWithFormat:@"set%@",
[key capitalizedString]];
SEL selector = NSSelectorFromString(setPropertyString);开发者_Python百科
NSMethodSignature * signature = ...
NSInvocation * invocation = ...
CGFloat arg = value;
void * argument = &arg;
[invocation setArgument:argument atIndex:2];
[invocation invoke];
}
This method works for one-word properties like "color" or "width", but fails on mulit-word properties like "lineSpacing" or "meaningOfLifeTheUniverseAndEverything" because the capitalize
method capitalizes the first letter while setting all subsequent letters to lowercase. Calling the above method using "lineSpacing" as the key results in failure, since the correct property setter would be setLineSpacing:
and not setLinespacing:
You're looking for setValue:forKey:
, which not only finds the correct setter selector but sends the message for you. It's part of the Key-Value Coding protocol; note that getters like myProperty
and setters like setMyProperty:
are called “Key-Value-Coding-compliant” for this reason.
I'm working on a method that will set a number of properties, by name, using property values stored in a dictionary.
See also the setValuesForKeysWithDictionary:
method, also part of the KVC protocol.
Apple hasn't made a public-facing function to do this, but the general algorithm is pretty simple:
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;
}
Before you go using this, however, keep in mind that there may be other ways to accomplish your goal. Investigate the existing APIs you're using before you go off and do this (which, I might add, will not work correctly if the accessor of a @property
is set to something different. I'm not aware of any function in the Objective-C runtime that will let you get the setter of a @property
.)
精彩评论