iOS获取属性类

我试图得到一个未知类的所有属性和每个属性的类的列表。 到目前为止,我得到一个对象的所有属性的列表(我recursion获取所有的超类)。 我在这篇文章中受到启发

+ (NSArray *)classPropsFor:(Class)klass { NSLog(@"Properties for class:%@", klass); if (klass == NULL || klass == [NSObject class]) { return nil; } NSMutableArray *results = [[NSMutableArray 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 char *propName = property_getName(property); if(propName) { NSString *propertyName = [NSString stringWithUTF8String:propName]; [results addObject:propertyName]; } NSArray* dict = [self classPropsFor:[klass superclass]]; [results addObjectsFromArray:dict]; } free(properties); return [NSArray arrayWithArray:results]; } 

所以现在我想要每个属性的类,我做:

 NSArray* properties = [PropertyUtil classPropsFor:[self class]]; for (NSString* property in properties) { id value= [self valueForKey:property]; NSLog(@"Value class for key: %@ is %@", property, [value class]); } 

问题是它适用于NSStrings,但不适用于自定义类,因为它返回null。 我想recursion地创build一个代表一个可以有其他对象的对象的字典,因为我认为我需要知道每个属性的类,是可能的吗?

您应该在存储propertyName的同时,为每个属性存储类(以stringforms)。 也许作为一个字典与属性名称作为键和类名作为值,反之亦然。

为了得到类名,你可以做这样的事情(在声明propertyName之后放置这个):

 NSString* propertyAttributes = [NSString stringWithUTF8String:property_getAttributes(property)]; NSArray* splitPropertyAttributes = [propertyAttributes componentsSeparatedByString:@"\""]; if ([splitPropertyAttributes count] >= 2) { NSLog(@"Class of property: %@", [splitPropertyAttributes objectAtIndex:1]); } 

string处理代码是因为这些属性包含许多信息 – 具体细节在这里指定: https : //developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection。 HTML

只是为此做了一个小小的方法。

 // Simple as. Class propertyClass = [customObject classOfPropertyNamed:propertyName]; 

可以在许多方面进行优化,但我喜欢它。


实现如下所示:

 -(Class)classOfPropertyNamed:(NSString*) propertyName { // Get Class of property to be populated. Class propertyClass = nil; objc_property_t property = class_getProperty([self class], [propertyName UTF8String]); NSString *propertyAttributes = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding]; NSArray *splitPropertyAttributes = [propertyAttributes componentsSeparatedByString:@","]; if (splitPropertyAttributes.count > 0) { // xcdoc://ios//library/prerelease/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html NSString *encodeType = splitPropertyAttributes[0]; NSArray *splitEncodeType = [encodeType componentsSeparatedByString:@"\""]; NSString *className = splitEncodeType[1]; propertyClass = NSClassFromString(className); } return propertyClass; } 

它是eppz!kit的一部分,在一个名为NSObject+EPPZRepresentable.h的开发对象表示NSObject+EPPZRepresentable.h 。 它实际上是做你最初的目标。

 // Works vica-versa. NSDictionary *representation = [customObject dictionaryRepresentation]; CustomClass = [CustomClass representableWithDictionaryRepresentation:representation]; 

它编码许多types,迭代槽集合,表示CoreGraphicstypes,UIColors,也表示/重build对象引用。


新版本甚至会把你的Ctypes名称命名结构types也吐出来:

 NSLog(@"%@", [self typeOfPropertyNamed:@"index"]); // unsigned int NSLog(@"%@", [self typeOfPropertyNamed:@"area"]); // CGRect NSLog(@"%@", [self typeOfPropertyNamed:@"keyColor"]); // UIColor 

作为eppz!模型的一部分 ,请随时在https://github.com/eppz/eppz.model/blob/master/eppz!model/NSObject%2BEPPZModel_inspecting.m#L111上使用方法实&#x73B0;

更新

这不适用于nil值。 相反,您应该使用运行时C API从相应的ivar或accessor方法获取类。

以下添加到一个NSObject类别的窍门。

 - (Class) classForKeyPath:(NSString*)keyPath { Class class = 0; unsigned int n = 0; objc_property_t* properties = class_copyPropertyList(self.class, &n); for (unsigned int i=0; i<n; i++) { objc_property_t* property = properties + i; NSString* name = [NSString stringWithCString:property_getName(*property) encoding:NSUTF8StringEncoding]; if (![keyPath isEqualToString:name]) continue; const char* attributes = property_getAttributes(*property); if (attributes[1] == '@') { NSMutableString* className = [NSMutableString new]; for (int j=3; attributes[j] && attributes[j]!='"'; j++) [className appendFormat:@"%c", attributes[j]]; class = NSClassFromString(className); } break; } free(properties); return class; }