IOS get property class

I am trying to get a list of all the properties of an unknown class and the class of each property. By the time I get a list of all the properties of the object (I do it recursively to get all the superclasses). I inspired this post.

+ (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]; } 

So now I want the class of each property, and I do:

 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]); } 

The problem is that it works for NSStrings or not for custom classes, for which it returns me null. I want to recursively create a dictionary that represents an object that can have other objects inside and, it seems to me, I need to know the class of each property, maybe?

+6
source share
4 answers

You should probably save the class (as a string) for each property while saving propertyName . Perhaps as a dictionary with a property name as a key name and a class as a value, or vice versa.

To get the class name, you can do something like this (put this right after declaring propertyName ):

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

The string processing code is related to the fact that the attributes include several pieces of information - the exact data is indicated here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html

+2
source

Just made a tiny method for this.

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

It can be optimized in many ways, but I like it.


The implementation is as follows:

 -(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; } 

This is part of eppz! kit , in a developing object declaration called NSObject+EPPZRepresentable.h . It actually does what you must achieve initially.

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

It encodes many types, iterates over collections, represents CoreGraphics, UIColors types, and also presents / restores object references.


The new version also returns you the names of C types and with the name struct types :

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

Part of the eppz model! feel free to use method implementations on <a3>

+7
source

UPDATED

This does not work for nil values. Instead, you should use the C runtime API to get the class from the corresponding ivar or accessor method.

+2
source

The following, added to the NSObject category, does the trick.

 - (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; } 
0
source

Source: https://habr.com/ru/post/916263/


All Articles