iOS get property class

后端 未结 4 2138
粉色の甜心
粉色の甜心 2021-02-06 09:55

I\'m trying to get a list of all the properties of an unknown class and the class of every property. By the moment I get a list of all the properties of an object(I do it recurs

相关标签:
4条回答
  • 2021-02-06 10:17

    You should probably store the class (as a string) for each property at the same time as you store the propertyName. Maybe as a dictionary with property name as the key and class name as the value, or vice versa.

    To get the class name, you can do something like this (put this right after you declare 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 handling code is because the attributes include a number of pieces of information - the exact details are specified here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html

    0 讨论(0)
  • 2021-02-06 10:24

    UPDATED

    This doesn't work for values that are nil. Instead you should use the runtime C API to obtain the class from the corresponding ivar or accessor method.

    0 讨论(0)
  • 2021-02-06 10:26

    Just made a tiny method for this.

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

    Could be optimized in many ways, but I love it.


    Implementation goes like:

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

    It is part of eppz!kit, within a developing object representer called NSObject+EPPZRepresentable.h. It actually does what you are to achieve originally.

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

    It encodes many types, iterate trough collections, represents CoreGraphics types, UIColors, also represent / reconstruct object references.


    New version spits you back even C type names and named struct types as well:

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

    Part of eppz!model, feel free to use method implementations at https://github.com/eppz/eppz.model/blob/master/eppz!model/NSObject%2BEPPZModel_inspecting.m#L111

    0 讨论(0)
  • 2021-02-06 10:41

    The following added to an 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 讨论(0)
提交回复
热议问题