-1

how to get and set a property value with runtime in Objective-C? in any argument type and return type

zixun
  • 257
  • 3
  • 6

1 Answers1

18

First we have to differentiate between properties and ivars. If an accessor is coded explicitly or if the property is not ivar-backed, it is called a "stored property".

A. Accessing a Property

Since a property is simply the declaration of accessor methods, accessing and getting properties means to execute a accessor method.

A property is universal to all instance objects of a class. So, first get it:

Class objectsClass = object_getClass( receiver );

Then you can get the property

objc_property_t property = class_getProperty( objectsClass, [propertyName cStringUsingEncoding:NSASCIIStringEnCoding] );

Having the property, you get the identifiers of the setter and getter.

SEL getter;
const char* getterName = property_copyAttributeValue( property, "G" ) 

G is for getter, S is for setter as described here.

IIRC, you get nil, if the accessor is not set explicitly (setter=…, getter=…), so you have to take the properties name following the naming conventions:

if (getter==NULL)
{
  getter = NSSelectorFromString( propertyName );
}
else
{
  getter = sel_getUid( getterName );
}

With a setter it is a bit more complicated, because you have to prefix the property's name with set and make the first character of the name uppercased. But simple string processing.

Now we can execute the accessor. This is for getters more complicated, because you have to differ from the return types: integral (id, char, unsigned int, …), floating-point (float, double, long double) and structures. You will find a function for each case and should cast the result. However for integral types (including pointers) it looks like this:

id value = objc_msgSend( receiver, getter );

B. Getting the Ivars Value

If you want to get or set the value of the ivar, it is the same way to get the property. After this you read the V attribute of the property to get the ivar's name. (Remember: @synthesize property=differentIvarName). Then you get the ivar:

objc_ivar ivar = class_getInstanceVariable( objectsClass, ivarName );

And get it:

id value = object_getIvar( object, ivar );

If it is a C type, you have to go a different way, for example

ptrdiff_t offset = ivar_getOffset( ivar );
double value = *((double*)(object+offset));

Analogue with setters.

All is typed in Safari without rechecking the docs. However it should be a deep pointer.

BTW: The type encoding are described here.

Community
  • 1
  • 1
Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50