On Feb 1, 2013, at 02:21 , Graham Cox <[email protected]> wrote:
> Well, I might pursue this line of thought if I had a clear understanding of
> how to reliably check the type of an arbitrary property.
Here are some fragments of the code I use to analyze properties. Note that this
is accessing @property information, not general method information:
> // Get a dictionary whose keys are the first character of each substring
> of a property attribute string,
> // and whose objects are the corresponding rest of each substring
>
> + (NSDictionary*) propertyAttributesForPropertyName: (NSString*) name
> forOwningClass: (Class) owningClass
> {
> NSMutableDictionary* result = [NSMutableDictionary dictionary];
>
> // Find the attribute string, if the property is defined
>
> const char* classPropertyName = [name cStringUsingEncoding:
> NSASCIIStringEncoding];
> NSAssert (classPropertyName, [NSString stringWithFormat: @"Invalid
> characters in property name %@ of class %@", name, NSStringFromClass
> (owningClass)]);
>
> objc_property_t classProperty = class_getProperty (owningClass,
> classPropertyName);
> if (!classProperty)
> return result;
>
> NSString* attributes = [NSString stringWithCString:
> property_getAttributes (classProperty) encoding: NSASCIIStringEncoding];
> if (!attributes)
> return nil;
>
> // Divide the string into substrings
>
> NSArray* components = [attributes componentsSeparatedByString: @","];
> for (NSString* component in components)
> {
> NSRange range = [component
> rangeOfComposedCharacterSequenceAtIndex: 0];
> if (!range.length)
> continue;
>
> NSString* componentCharacter = [component substringWithRange:
> range];
> NSString* restOfComponent = [component substringFromIndex:
> range.location + range.length];
> if (!componentCharacter || !componentCharacter.length ||
> !restOfComponent)
> return nil;
>
> NSAssert (![result objectForKey: componentCharacter], @"Invalid
> property attribute string");
>
> [result setObject: restOfComponent forKey: componentCharacter];
> }
>
> return result;
> }
Use the above to get some useful information about the property:
> NSString* typeEncoding = [propertyAttributes objectForKey: @"T"];
> if (!typeEncoding || [typeEncoding isEqualToString: @""])
> return YES;
>
> BOOL isReadOnly = !![propertyAttributes objectForKey: @"R"];
> BOOL isCopy = !![propertyAttributes objectForKey: @"C"];
Examine the property type:
> // Get the type character for a non-struct type
>
> if ([typeEncoding characterAtIndex: 0] != '{')
> propertyEncodedType = [typeEncoding substringToIndex: 1];
>
> // Or get the type string for a struct type
>
> else
> {
> // Ignore the property if the type encoding is not of the
> form '{' <non-null-struct-tag-name> '='
>
> NSRange range = [typeEncoding rangeOfString: @"="];
> if (!range.length)
> return YES;
>
> if (range.location < 2)
> return YES;
>
> // Take everything up to and including to the '='
>
> NSString* structEncoding = [typeEncoding substringToIndex:
> range.location + range.length];
>
> // Look for a structure that we recognize
>
> NSString* pointTypeString = [NSString stringWithCString:
> @encode (CGPoint) encoding: NSASCIIStringEncoding];
>
> if ([pointTypeString hasPrefix: structEncoding])
> propertyEncodedType = pointTypeString;
> …
> }
You might be interested in a different subset of property types, but this shows
at least part of the way to get there.
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]