5
\$\begingroup\$

playerObject is an NSDictionary from JSONObjectWithData:options:error.

I'm trying to update a CoreData entity.

if ([results count] > 0)
{
    newPlayer = (Player *)[results objectAtIndex:0];
} else {
    //Add a new player
    newPlayer = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:temporaryContext];
}
//Assume these exist and are not null
newPlayer.email = [playerObject objectForKey:@"email"];
newPlayer.username = [playerObject objectForKey:@"username"];
newPlayer.continent = [playerObject objectForKey:@"continent"];

//Dates
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"yyyy-MM-dd hh:mm:ss"];
newPlayer.created = [df dateFromString: [playerObject objectForKey:@"created"]];

//Optional properties
if ([[playerObject objectForKey:@"title"] isKindOfClass:[NSNull class]])
{
    newPlayer.title = nil;
} else {
    newPlayer.title = [[playerObject objectForKey:@"title"] stringValue];
}

Is there any way to make it less verbose? Have I left myself open to any issues?

\$\endgroup\$
  • 1
    \$\begingroup\$ Take a look at JSRestNetworkKit and stop parsing the JSON yourself :) github.com/JaviSoto/JSRestNetworkKit \$\endgroup\$ – Javier Soto Sep 5 '12 at 15:53
  • \$\begingroup\$ Looks interesting but I'd just want to use the mapping from a dictionary to CoreData entity. Would this be possible? \$\endgroup\$ – djskinner Sep 17 '12 at 9:10
  • 1
    \$\begingroup\$ You mean without making requests to an API? Yes, absolutely, you would just have to make your CoreData entities inherit from JSBaseCoreDataBackedEntity and use + (id)updateOrInsertIntoManagedObjectContext:(NSManagedObjectContext *)managedObjectContext withDictionary:(NSDictionary *)dictionary; \$\endgroup\$ – Javier Soto Sep 17 '12 at 18:37
  • 1
    \$\begingroup\$ Excellent. I'll take a look into that then, since I'm using JSON-RPC for the web service. \$\endgroup\$ – djskinner Sep 18 '12 at 11:08
2
\$\begingroup\$
if ([results count] > 0)
{
    newPlayer = (Player *)[results objectAtIndex:0];
} else {
    //Add a new player
    newPlayer = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:temporaryContext];
}

This chunk of code could be replaced with:

newPlayer = (Player *)([results firstObject] ?: [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:temporaryContext]);

if ([[playerObject objectForKey:@"title"] isKindOfClass:[NSNull class]])
{
    newPlayer.title = nil;
} else {
    newPlayer.title = [[playerObject objectForKey:@"title"] stringValue];
}

This chunk of code could also be slightly better.

NSString *newTitle = playerObject[@"title"];
newPlayer.title = [newTitle isEqual:[NSNull null]] ? nil : [newTitle stringValue];

The last comment that I'll make is a strong recommendation that you use constants for your keys rather than literal strings. Defined constants will auto-complete for you, which is nice, but more importantly, it will eliminate misspellings entirely.

static NSString * const kKey_Player = @"Player";
static NSString * const kKey_Title = @"title";
// etc.

Then use it as such:

NSString *newTitle = playerObject[kKey_Title];

Under the covers, this actually doesn't change in the slightest what the code does. Even when you use string literals, a memory location is still allocated for them. The advantage here is that you eliminate programmer mistakes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.