Objective-C Get a Class Property from String

Objective-C get a class property from string

The Key Value Coding mechanism allows you to interact with a class's properties using string representations of the property names. So, for example, if your Record class has a property called column1, you can access that property as follows:

NSString* dataToGet = @"column1";
id value = [myRecord valueForKey:dataToGet];

You can adapt that principle to your specific needs.

Get property name as a string

You can try this:

unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList([self class], &propertyCount);

NSMutableArray * propertyNames = [NSMutableArray array];
for (unsigned int i = 0; i < propertyCount; ++i) {
objc_property_t property = properties[i];
const char * name = property_getName(property);
[propertyNames addObject:[NSString stringWithUTF8String:name]];
}
free(properties);
NSLog(@"Names: %@", propertyNames);

detect the class of a property with name in objective-c


i have the name of this property as NSString

You can use the function class_getProperty(Class cls, const char *name) to find the property for a given class. Then use property_getAttributes(objc_property_t property) to get the property's attributes, including the encoded type string. Read the Declared Properties section of the Objective-C Runtime Programming Guide for more info.

List of class properties in Objective-C

So more precisely, you want dynamic, runtime observaion of the properties, if I got it correctly. Do something like this (implement this method on self, the class you want to introspect):

#import <objc/runtime.h>

- (NSArray *)allPropertyNames
{
unsigned count;
objc_property_t *properties = class_copyPropertyList([self class], &count);

NSMutableArray *rv = [NSMutableArray array];

unsigned i;
for (i = 0; i < count; i++)
{
objc_property_t property = properties[i];
NSString *name = [NSString stringWithUTF8String:property_getName(property)];
[rv addObject:name];
}

free(properties);

return rv;
}

- (void *)pointerOfIvarForPropertyNamed:(NSString *)name
{
objc_property_t property = class_getProperty([self class], [name UTF8String]);

const char *attr = property_getAttributes(property);
const char *ivarName = strchr(attr, 'V') + 1;

Ivar ivar = object_getInstanceVariable(self, ivarName, NULL);

return (char *)self + ivar_getOffset(ivar);
}

Use it like this:

SomeType myProperty;
NSArray *properties = [self allPropertyNames];
NSString *firstPropertyName = [properties objectAtIndex:0];
void *propertyIvarAddress = [self getPointerOfIvarForPropertyNamed:firstPropertyName];
myProperty = *(SomeType *)propertyIvarAddress;

// Simpler alternative using KVC:
myProperty = [self valueForKey:firstPropertyName];

Hope this helps.

iOS get property class

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

Get an object properties list in Objective-C

I just managed to get the answer myself. By using the Obj-C Runtime Library, I had access to the properties the way I wanted:

- (void)myMethod {
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList([self class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *propName = property_getName(property);
if(propName) {
const char *propType = getPropertyType(property);
NSString *propertyName = [NSString stringWithCString:propName
encoding:[NSString defaultCStringEncoding]];
NSString *propertyType = [NSString stringWithCString:propType
encoding:[NSString defaultCStringEncoding]];
...
}
}
free(properties);
}

This required me to make a 'getPropertyType' C function, which is mainly taken from an Apple code sample (can't remember right now the exact source):

static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T') {
if (strlen(attribute) <= 4) {
break;
}
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "@";
}

How to setup a class property in objective C?

Since Xcode 8 you can define a class property in the header file of YourClass, using the "class" identifier like:

@interface YourClass : NSObject

@property (class, strong, nonatomic) NSTimer *timer;

@end

To use the class property in class methods in your implementation you need to asign a static instance variable to your class property. This allows you to use this instance variable in class methods (class methods start with "+").

@implementation YourClass

static NSTimer *_timer;

You have to create getter and setter methods for the class property, as these will not be synthesized automatic.

+ (void)setTimer:(NSTimer*)newTimer{
if (_timer == nil)
_timer = newTimer;
}

+ (NSTimer*)timer{
return _timer;
}

// your other code here ...

@end

Now you can access the class property from all over the app and other methods with the following syntax - here are some examples:

NSTimeInterval seconds = YourClass.timer.fireDate.timeIntervalSinceNow;

[[YourClass timer] invalidate];

You will always send messages to the same object, no problems with multiple instances!

Please find an Xcode 11 sample project here: GitHub sample code

get property from id class

there are many ways

you can cast it if you know the type at compile time

id property=((MyClass *)instance).myProperty;
((MyClass *)instance).myProperty = property;

or not using dot syntax

id property=[instance myProperty];
[instance setMyProperty:property];

or using valueForKey:

id property=[instance valueForKey:@"myProperty"];
[instance setValue:property forKey:@"myProperty"];

How do I get the value from a class property in Objective-C?

That should be valueForKey instead of objectForKey. objectForKey is an NSDictionary instance method.
Besides that there's a potentional mistake in your code. Your return type in the above method is string but you don't cast it to NSString before returning.Even if you're sure that it'll always return a string it's good practice to avoid any doubts. And when declaring an NSString property you should copy it rather than retaining it. And, what's the point in declaring a "me" variable if you can easily say:

[self valueForkey:paramName];


Related Topics



Leave a reply



Submit