Bach
Bach

Reputation: 2684

NSManagedObject - How to get the type of the property

I am trying to parse a json string straight into a managed object. The json string contains all strings, but my Entity has Date objects.

if this is my json string

{
"name":"John",
"dob": "12/12/2008",
etc...
}

and here's my entity Person:

name : NSString
dob: Date
etc...

I want to parse that json straight through by looping through the keys of the Json dict, and setting the values to the matching keys of my entity:

Person *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *keys = [jsonDict allKeys];

for (NSString *key in keys) {

 [aPerson setValue:[jsonDict valueForKey:key] forKey:key];

}

This only works if all my entity's properties are NSStrings.

How can I get the type/class of my entity's property to be able to set the various types?

eg. if key = @"dob" how can I get the type/class of aPerson.dob?

so my code will look something like:

Person *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *keys = [jsonDict allKeys];

for (NSString *key in keys) {
    if([[aPerson objectForKey:key] isKindOfClass:[NSDate class]])
    {
       // Create an NSDate object
    }else{
       [aPerson setValue:[jsonDict valueForKey:key] forKey:key];
    }
}

thanks

UPDATE:

Ok I tried using the isKindOfClass and here's the result was:

// for key = @"name" 
// aPerson.name is NSString
[[aPerson valueForKey:key] isKindOfClass:[NSString class]] => TRUE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => TRUE

// for key = @"age"
// aPerson.age is NSNumber
[[aPerson valueForKey:key] isKindOfClass:[NSNumber class]] => TRUE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => TRUE

// for key = @"dob"
// aPerson.dob is NSDate
[[aPerson valueForKey:key] isKindOfClass:[NSDate class]] => FALSE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => FALSE

how is that? @dynamic dob and NSDate, is notOfClass NSDate!

please tell me what I am missing!

Upvotes: 1

Views: 4127

Answers (3)

Urkman
Urkman

Reputation: 1318

I know, this is a late answer, but as I was search today for a good solution... This is what I'm using now:

NSEntityDescription * myEntity = [object entity];
NSDictionary * attributes = [myEntity attributesByName];
if ([[[attributes objectForKey:key] attributeValueClassName] isEqualToString:@"NSDate"]) {
    // this type is NSDate
}                        

Hope this helps :)

Upvotes: 3

Bach
Bach

Reputation: 2684

Thanks a lot to Rog, for sending me in the right direction, I ended up overriding my setter as below:

-(void)setDob:(id)value
{
    [self willAccessValueForKey:@"dob"];
    if ([value isKindOfClass:[NSString class]]) {
        [self setPrimitiveValue:[DateFormatter dateFromString:value] forKey:@"dob"];
    }else{
        [self setPrimitiveValue:value forKey:@"dob"];
    }
    [self didChangeValueForKey:@"dob"];
}

and all works great now, instead of a 1000 lines of code parsing, it's all done in 3! nice one!

Upvotes: 0

Rog
Rog

Reputation: 18670

You can either convert your JSON string to NSDate and then assign it to your NSManagedObject, or you can create a custom setter in your Person class that takes an NSString and returns NSDate. Here's an example:

- (NSDate*)convertStringToDate:(NSString*)dateString {  
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    // this is imporant - we set our input date format to match our input string
    // if format doesn't match you'll get nil from your string, so be careful
    [dateFormatter setDateFormat:@"d MMMM yyyy"];
    NSDate *dateFromString = [dateFormatter dateFromString:dateString];
    [dateFormatter release];
    return dateFromString;
}

Upvotes: 1

Related Questions