Re: KVC and Core Foundation types
Re: KVC and Core Foundation types
- Subject: Re: KVC and Core Foundation types
- From: Quincey Morris <email@hidden>
- Date: Fri, 01 Feb 2013 09:17:54 -0800
On Feb 1, 2013, at 02:21 , Graham Cox <email@hidden> 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@hidden)
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:
This email sent to email@hidden