Re: KVC and Core Foundation types
Re: KVC and Core Foundation types
- Subject: Re: KVC and Core Foundation types
- From: Graham Cox <email@hidden>
- Date: Fri, 01 Feb 2013 17:54:45 +1100
On 01/02/2013, at 5:18 PM, Quincey Morris <email@hidden> wrote:
>> /* CoreGraphics - CGPath.h
>> Copyright (c) 2001-2011 Apple Inc.
>> All rights reserved. */
>>
>> typedef struct CGPath *CGMutablePathRef;
>> typedef const struct CGPath *CGPathRef;
>
> So KVC isn't going to know these are objects. Interestingly, types like 'dispatch_semaphore_t' aren't declared this way, so they probably *do* work via 'valueForKey:' without assistance.
Aha... that is probably what's going on. I wonder why these aren't typedef'd as CFTypeRef?
Anyway, as long as I'm aware of the problem with KVC, and can rely on it hitting -valueForUndefinedKey:, a fairly general solution isn't that bad.
I'm mostly interested in using KVC here for automatically archiving without having to write hundreds of lines of code of the kind [encoder encodeObject:<blah> forKey:<bleh>];
Those objects that can take advantage of this inherit from a simple base class which exports one public class method, +archivableProperties, returning a NSSet of keys. By doing this rather than using runtime introspection to find all the properties allows objects to only specify those that they want to auto-archive, and others can be ignored or handled as a special case if needed. Then, this same base class implements default -initWithCoder and encodeWithCoder: methods that iterate these keys using KVC to get and set the property values.
For the errant CFTypes, I hit -valueForUndefinedKey: and -setValue:forUndefinedKey:, overridden in this base class. This then checks whether in fact the selector really is undefined, and if not, it forces the value to be returned using -performSelector. It then passes off these CFTypes to some conversion utilities that, for each type of interest, grabs all the necessary values and puts them into a dictionary, and returns that. The dictionary of course can be archived. On dearchiving, I simply reverse the process, building new CFType objects from the dictionaries.
If an object wants to override -initWithCoder and -encodeWithCoder and do things the long-winded way, it can do so and will still work, it just needs to not return those properties in +archivableProperties.
The goal of all this was so that each subclass only needs to override +archivableProperties and return the combined list of super's property keys and its own, and will be fully archivable with no more work, even if the properties run into many dozens (as they do), and are mostly of CFTypes (as they often are). In addition it must eventually work on iOS, which is why I'm avoiding certain objects in favour of CFTypes, e.g. CGColorRef rather than NSColor.
--Graham
_______________________________________________
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