通过Objective-C Runtime函数这个问题得到了很好的解决。
总的来说呢就是通过下面两个函数:
objc_property_t* props = class_copyPropertyList([TestModelclass], &count);
这个可以获得一个类的所有属性的一个数组。
const char * type =property_getAttributes(property);
这个函数可以获得属性的类型。
需要的头文件有
- #import <objc/message.h>
- #import <objc/runtime.h>
大概的代码如下:
- unsigned int count;
- objc_property_t* props = class_copyPropertyList([TestModel class], &count);
- for (int i = 0; i < count; i++) {
- objc_property_t property = props[i];
- const charchar * name = property_getName(property);
- NSString *propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
- const charchar * type = property_getAttributes(property);
- NSString *attr = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
- NSString * typeString = [NSString stringWithUTF8String:type];
- NSArray * attributes = [typeString componentsSeparatedByString:@","];
- NSString * typeAttribute = [attributes objectAtIndex:0];
- NSString * propertyType = [typeAttribute substringFromIndex:1];
- const charchar * rawPropertyType = [propertyType UTF8String];
- if (strcmp(rawPropertyType, @encode(float)) == 0) {
- //it's a float
- } else if (strcmp(rawPropertyType, @encode(int)) == 0) {
- //it's an int
- } else if (strcmp(rawPropertyType, @encode(id)) == 0) {
- //it's some sort of object
- } else {
- // According to Apples Documentation you can determine the corresponding encoding values
- }
- if ([typeAttribute hasPrefix:@"T@"] && [typeAttribute length] > 1) {
- NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)]; //turns @"NSDate" into NSDate
- Class typeClass = NSClassFromString(typeClassName);
- if (typeClass != nil) {
- // Here is the corresponding class even for nil values
- }
- }
- }
- free(props);
另一种方法是自己去实现获取属性类型的方法
- //获取属性名称数组
- - (NSDictionary *)classPropsFor:(Class)klass
- {
- if (klass == NULL) {
- return nil;
- }
- NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
- unsigned int outCount, i;
- objc_property_t *properties = class_copyPropertyList(klass, &outCount);
- for (i = 0; i < outCount; i++) {
- objc_property_t property = properties[i];
- const charchar *propName = property_getName(property);
- if(propName) {
- const charchar *propType = getPropertyType(property);
- NSString *propertyName = [NSString stringWithUTF8String:propName];
- NSString *propertyType = [NSString stringWithUTF8String:propType];
- NSLog(@"propertyName %@ propertyType %@", propertyName, propertyType);
- [results setObject:propertyType forKey:propertyName];
- }
- }
- free(properties);
- // returning a copy here to make sure the dictionary is immutable
- return [NSDictionary dictionaryWithDictionary:results];
- }
- //获取属性的方法
- static const charchar *getPropertyType(objc_property_t property) {
- const charchar *attributes = property_getAttributes(property);
- //printf("attributes=%s\n", attributes);
- char buffer[1 + strlen(attributes)];
- strcpy(buffer, attributes);
- charchar *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.
- NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding];
- return (const charchar *)[name cStringUsingEncoding:NSASCIIStringEncoding];
- }
- 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:
- NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
- return (const charchar *)[name cStringUsingEncoding:NSASCIIStringEncoding];
- }
- }
- return "";
- }