Luther Baker
Luther Baker

Reputation: 7341

Coercing a KVC type

I would like to parse XML to populate KVC compliant objects but, my parser is very dumb, it simply assembles NSStrings from the XML attributes/tags and tries to set them via KVC.

This works for actual strings and numbers (I believe) but I need to also set dates. The problem is obviously that the parser doesn't know the string represents a date and it tries to sit it using the vanilla KVC calls - afterwhich the KVC framework complains about the type mismatch (setting a string on a date field).

Is there a programmatic way to 'intercept' invocations into the KVC framework such that I can alter the data being set (run a date string through an NSDateFormatter)?

I could put some intelligence into the parser but before doing so, are there any other well-known solutions for this type of problem?

Upvotes: 1

Views: 248

Answers (2)

Pawel
Pawel

Reputation: 4715

This might not be the perfect solution, but... I'd like to share my ideas ;)

So, first of all, take a look here: Key-Value Coding - Validation. That document describes a neat way to validate your variable the moment it's set via KVC. You could use this to your advantage by:

  1. First implement KV Validation method for your class variable
  2. Set your value
  3. In your validation method check if it's a date/string/whatever you wish - and change it to proper type.

This should provide a clean implementation for ensuring proper type.

Cheers, Pawel

Upvotes: 2

paulbailey
paulbailey

Reputation: 5346

With KVC, everything goes through a default implementation of setValue:forKey: whichs calls the appropriate mutator method (as described here).

You can just override setValue:forKey: to check for the key or keys that need transforming, and make appropriate changes.

- (void)setValue:(id)value forKey:(NSString *)key
{
    if([key isEqualToString:@"someDate"]) {
        NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
        someDate = [dateFormatter dateFromString:value];
        value = somedate;
    }

    [super setValue:value forKey:key];
}

That's from memory, so no guarantees whether it'll actually compile and run. ;-)

Upvotes: 0

Related Questions