How to detect a property return type in Objective-C

不问归期 提交于 2019-11-26 20:13:17

问题


I have an object in objective-c at runtime, from which I only know the KVC key and I need to detect the return value type (e.g. I need to know if its an NSArray or NSMutableArray) of this property, how can I do that?


回答1:


You're talking about runtime property introspection, which happens to be something that Objective-C is very good at.

In the case you describe, I'm assuming you have a class like this:

@interface MyClass
{
    NSArray * stuff;
}
@property (retain) NSArray * stuff;
@end

Which gets encoded in XML something like this:

<class>
    <name>MyClass</name>
    <key>stuff</key>
</class>

From this information, you want to recreate the class and also give it an appropriate value for stuff.

Here's how it might look:

#import <objc/runtime.h>

// ...

Class objectClass;       // read from XML (equal to MyClass)
NSString * accessorKey;  // read from XML (equals @"stuff")

objc_property_t theProperty =
    class_getProperty(objectClass, accessorKey.UTF8String);

const char * propertyAttrs = property_getAttributes(theProperty);
// at this point, propertyAttrs is equal to: T@"NSArray",&,Vstuff
// thanks to Jason Coco for providing the correct string

// ... code to assign the property based on this information

Apple's documentation (linked above) has all of the dirty details about what you can expect to see in propertyAttrs.




回答2:


Cheap answer: use the NSObject+Properties source here.

It implements the same methodology described above.




回答3:


The preferred way is to use the methods defined in the NSObject Protocol.

Specifically, to determine if something is either an instance of a class or of a subclass of that class, you use -isKindOfClass:. To determine if something is an instance of a particular class, and only that class (ie: not a subclass), use -isMemberOfClass:

So, for your case, you'd want to do something like this:

// Using -isKindOfClass since NSMutableArray subclasses should probably
// be handled by the NSMutableArray code, not the NSArray code
if ([anObject isKindOfClass:NSMutableArray.class]) {
    // Stuff for NSMutableArray here
} else if ([anObject isKindOfClass:NSArray.class]) {
    // Stuff for NSArray here

    // If you know for certain that anObject can only be
    // an NSArray or NSMutableArray, you could of course
    // just make this an else statement.
}



回答4:


This is really a comment addressing an issue raised by Greg Maletic in response to answer provided by e.James 21APR09.

Agreed that Objective-C could use a better implementation for getting these attributes. Below is a method I quickly threw together to retrieve attributes of a single object property:

- (NSArray*) attributesOfProp:(NSString*)propName ofObj:(id)obj{

    objc_property_t prop = class_getProperty(obj.class, propName.UTF8String);
    if (!prop) {
       // doesn't exist for object
       return nil;
    }
    const char * propAttr = property_getAttributes(prop);
    NSString *propString = [NSString stringWithUTF8String:propAttr];
    NSArray *attrArray = [propString componentsSeparatedByString:@","];
    return attrArray;
}

Partial list of attribute keys:

  • R Read-only
  • C Copy of last value assigned
  • & Reference to last value assigned
  • N Nonatomic property
  • W Weak reference

Full list at Apple




回答5:


You can use isKindOfClass message

if([something isKindOfClass:NSArray.class])
     [somethingElse action];



回答6:


If you know that the property is defined :

        id vfk = [object valueForKey:propertyName];
        Class vfkClass = vfk.class;

And compare with isKindOfClass, isSubClass, etc.



来源:https://stackoverflow.com/questions/769319/how-to-detect-a-property-return-type-in-objective-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!