property_getAttributes() does not make difference between retain, strong, weak and assign properties when set read-only

1.3k views Asked by At

I'm trying to get the property attributes of an object with the property_getAttributes() runtime function. Some properties are set read-only. But the problem comes when I try to make the difference between retain/strong, weak and assign properties. e.g.:

Let's say we have:

@interface MyObject : NSObject
@property (assign, readonly) NSObject *prop1;
@property (strong, readonly) NSObject *prop2;
@property (weak, readonly) NSObject *prop3;
@end

We get the property list and print

int outCount;
objc_property_t *properties = class_copyPropertyList([MyObject class], &outCount);
for(i = 0; i < outCount; i++) {
    objc_property_t property = properties[i];
    const char *c_attributes = property_getAttributes(property);
    printf("%s", c_attributes);
}
free(properties);

The result is:

T@"NSObject",R,V_prop1
T@"NSObject",R,V_prop2
T@"NSObject",R,V_prop3

...so no specific code for weak, strong/retain, assign properties when they are read-only :(

The question is: is there any other way to know if the property is weak, strong/retain, assign?

2

There are 2 answers

0
Ryan Dignard On

To answer your question quickly, the answer is no.

The issue here is that memory management semantics for properties (those are assign, unsafe_unretained, strong, weak, copy in ARC and assign, retain, copy in MRC) only have any application in automatically generated setter code. Should you write your own setter for the property you are of course encouraged to implement the semantic yourself (but not required). The getter of these properties are not modified at all by these property attributes. Consider this code:

@interface FooBar ()
@property (nonatomic, strong, readonly) NSString* foobar;
@end

@implementation FooBar
- (NSString*) foobar {
    return [NSString stringWithFormat:@"aString"];
}

In these situations the caller will make a either a strong or weak reference and the return value must live for at least as long as the calling code needs to complete the statement. In the case of a weak reference it will go to nil afterwards since a property with strong does not guarantee that the referenced object will be kept for you. Ultimately, memory management on readonly properties are nothing more than a placebo that end up there mostly by either habit or style @property (nonatomic, readonly) ... is perfectly legal, but confusing when we are used to encountering a memory attribute in the property declaration.

PS: There's another function in the runtime called property_copyAttributeList which I find much easier for parsing this information (it uses structs to break up the components for you).

0
miya On

I haven't tried your code, but according to

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/objcruntimeguide/articles/ocrtpropertyintrospection.html

R The property is read-only (readonly)

C The property is a copy of the value last assigned (copy).

& The property is a reference to the value last assigned (retain).

N The property is non-atomic (nonatomic).

G The property defines a custom getter selector name. The name follows the G (for example, GcustomGetter,).

S The property defines a custom setter selector name. The name follows the S (for example, ScustomSetter:,).

D The property is dynamic (@dynamic).

W The property is a weak reference (__weak).

P The property is eligible for garbage collection.

t Specifies the type using old-style encoding.