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?
-
1\$\begingroup\$ Take a look at JSRestNetworkKit and stop parsing the JSON yourself :) github.com/JaviSoto/JSRestNetworkKit \$\endgroup\$Javier Soto– Javier Soto2012年09月05日 15:53:02 +00:00Commented 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\$djskinner– djskinner2012年09月17日 09:10:25 +00:00Commented 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\$Javier Soto– Javier Soto2012年09月17日 18:37:15 +00:00Commented 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\$djskinner– djskinner2012年09月18日 11:08:17 +00:00Commented Sep 18, 2012 at 11:08
1 Answer 1
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.