views:

632

answers:

2

I'm using the runtime functions to get the type of a property (thanks to eJames for helping me to figure out this way). The attribute string of the property looks like this:

T@"NSArray",&,Vstuff

I need to check if the property type is an array, at the moment I'm doing it like this:

 - (BOOL)valueForKeyIsArray:(NSString *)key fromTagret:(id)target
{
    NSString *lowerCaseKey = [self convertToKVCKey:key];

    objc_property_t property = class_getProperty([target class], [lowerCaseKey UTF8String]);
    NSString *propertyAttrs = [NSString stringWithUTF8String:property_getAttributes(property)];
    NSString *encodedType = @"@\"NSArray\"";

    NSRange range = [propertyAttrs rangeOfString:encodedType options:NSLiteralSearch];
    return range.location != NSNotFound;
}

But since Apple can change the type definition string at any time, I would like to generate this @"NSArray" type string. I tried it with @encode(), but it did not work:

NSString *encodedType = [NSString stringWithUTF8String:@encode(NSArray *)];

So how can I generate this type string? Or is there a better way to check if this property attributes contain the array type?

+1  A: 

There is no way to check this. In object-c source code the variables being typed as "NSArray *" is only there for the compiler to issue warnings. It has no meaning, and does not exist at runtime. If you mis-typed an NSArray as an NSString, you would get lots of warnings when compiling, but you're code would behave exactly the same when run. At runtime all that is known is that the ivar/property is "an object".

Another way to think of it, is that once objc is compiled, all object references are "id" references.

Jon Hess
Actually you are right, the object references are "id" at runtime, but this does not matter in my case. The test works for me and I my Question is, how I can generate this @"NSArray" type string, because I don't want to hardcode it.
Enyra
You can get a string representation of the class of an object with NSStringFromClass([obj class]). Similarly, you can get the string representation of a class with NSStringFromClass([NSArray self]).@encode(NSArray) produces "{NSArray=#}"Where@encode(NSArray) produces "@"I'm not sure if that's what you were after, hopefully it will help.
Jon Hess
A: 

Just accept that if the runtime changes, your code will break, and move on. However, I think you might be miscategorizing ivars of type NSMutableArray *, CFArrayRef, or CFMutableArrayRef. You also seem to be assuming all keys correspond directly to a declared property.

The cleanest solution might be to assert that the sample object being used for the test (the target) must have a non-nil value for that key, and just grab the value and test that [[target valueForKey:key] isKindOfClass:[NSArray class]].

Jeremy W. Sherman