我需要使用反射来调用setter。要做到这一点,我需要选择器。但是我的代码中的setterName var为nil。我班上有安装和吸气。这是我的代码
objc_property_t *allProperties = class_copyPropertyList([object class], &allPropertyCount);
objc_property_t prop = class_getProperty(cls, propName);
for (unsigned int i = 0; i < allPropertyCount; i++) {
prop = allProperties[i];
}
char *setterName = property_copyAttributeValue(prop, "S");
SEL selector = NSSelectorFromString(setterName);
if([object respondsToSelector:@selector(selector)]){
return selector;
}
return nil;
答案 0 :(得分:3)
仅当属性分别定义自定义setter或getter时,才会设置“S”和“G”属性。您的代码需要检查setterName
是否为NULL,如果是,则从属性名称生成setter名称。
答案 1 :(得分:3)
回复有点迟,希望这对某人有用!
我启用了ARC,我正在使用生成的getter / setter。
// NSObject+Properties.m
#import "NSObject+Properties.h"
#import "objc/runtime.h"
@implementation NSObject (Properties)
static const char * getPropertyType(objc_property_t property) {
//Borrowed from http://stackoverflow.com/questions/754824/get-an-object-attributes-list-in-objective-c
//Many contributors to final solution
const char *attributes = property_getAttributes(property);
printf("attributes=%s\n", attributes);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T' && attribute[1] != '@') {
// it's a C primitive type:
/*
if you want a list of what will be returned for these primitives, search online for
"objective-c" "Property Attribute Description Examples"
apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc.
*/
return (const char *)[[NSData dataWithBytes:(attribute + 1) length:strlen(attribute) - 1] bytes];
}
else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) {
// it's an ObjC id type:
return "id";
}
else if (attribute[0] == 'T' && attribute[1] == '@') {
// it's another ObjC object type:
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "";
}
- (NSDictionary *) getClassProperties
{
//Borrowed from http://stackoverflow.com/questions/754824/get-an-object-attributes-list-in-objective-c
//Many contributors to final solution
if (self == NULL || self == nil) {
return nil;
}
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithUTF8String:propName];
NSString *propertyType = [NSString stringWithUTF8String:propType];
[results setObject:propertyType forKey:propertyName];
}
}
free(properties);
// returning a copy here to make sure the dictionary is immutable
return [NSDictionary dictionaryWithDictionary:results];
}
-(void) setProperty:(NSString *) propertyName value:(id) value {
SEL selector = [self buildGenericSetterForPropertyName:propertyName];
if( selector != NULL ) {
//The class responds to the selector
NSMethodSignature *aSignature = [[self class] instanceMethodSignatureForSelector:selector];
NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
[anInvocation setSelector:selector];
[anInvocation setTarget:self];
[anInvocation setArgument:&value atIndex:2];
[anInvocation invoke];
}
else {
//We don't know what the setter is, so directly access the iVar
Ivar iVar = class_getInstanceVariable([self class],[propertyName UTF8String]);
object_setIvar(self, iVar,value);
}
}
-(SEL) buildGenericSetterForPropertyName:(NSString *) name {
//Borrowed from https://github.com/AlanQuatermain/aqtoolkit/blob/master/Extensions/NSObject%2BProperties.m
NSMutableString * str = [NSMutableString stringWithString: @"set"];
[str appendString: [[name substringToIndex: 1] uppercaseString]];
if ( [name length] > 1 )
[str appendString: [name substringFromIndex: 1]];
//addition - the setter will accept one argument
[str appendString:@":"];
if( [[self class] instancesRespondToSelector:NSSelectorFromString(str)]) {
return NSSelectorFromString(str);
}
else {
return NULL;
}
}
@end