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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 25, 2012 at 13:05
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Take a look at JSRestNetworkKit and stop parsing the JSON yourself :) github.com/JaviSoto/JSRestNetworkKit \$\endgroup\$ Commented Sep 5, 2012 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\$ Commented Sep 17, 2012 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\$ Commented Sep 17, 2012 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\$ Commented Sep 18, 2012 at 11:08

1 Answer 1

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.

answered Jul 5, 2014 at 18:34
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.