Assuming you're fine with asking the metaclass (ie, you don't want to allow for potential instance-specific patches to the dispatch table), you can get property attributes from the runtime. Specifically:
// get the property; yes: that's a C string. This can see only things
// declared as @property
objc_property_t property =
class_getProperty([instance class], "propertyName");
/* check property for NULL here */
// get the property attributes.
const char *propertyAttributes = property_getAttributes(property);
You can then check those attributes for read-only:
NSArray *attributes =
[[NSString stringWithUTF8String:propertyAttributes]
componentsSeparatedByString:@","];
return [attributes containsObject:@"R"];
If you want to be completely thorough, you should also check protocols via class_copyProtocolList
and protocol_getProperty
, in order to catch any @property
s that are incorporated into the class that way and — as noted below by Gabriele — some caveats apply around class extensions.