当前位置: 动力学知识库 > 问答 > 编程问答 >

ios - Using Core Data Find or Create Pattern in Generic Method

问题描述:

I have a Generic method which adds data from a JSON into a Managed Object based on the keys in the JSON and in the entity.

I have read Apple's documentation here but I somehow can't seem to walk through the data after the fetch in order to apply the Find or Create pattern.

I don't want to use three nested loops to do that, is there another way?

Should I be looping over jsonArrayData or entityMatchingNames

- (void) safeSetValuesForKeysWithDictionary:(NSArray *)jsonArrayData : (NSNumber *) entitySpecifier{

//Flag to determine entity name

NSString *entityName;

NSString *idName;

if([entitySpecifier isEqual:@1]){

entityName = @"Zones";

[email protected]"zoneID";

}else if([entitySpecifier isEqual:@2]){

entityName = @"Categories";

[email protected]"categoryID";

}else if ([entitySpecifier isEqual:@3]){

entityName = @"Companies";

[email protected]"companyID";

}

//get entity

NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.elRehabCoreData.managedObjectContext];

//get attributes of entity in core data

NSDictionary *entityAttributes = [entity attributesByName];

// Get the ids from json in sorted order.

NSMutableArray *entityIDs = [[NSMutableArray alloc]init];

for (NSDictionary *jsonValues in jsonArrayData) {

id value = [jsonValues objectForKey:idName];

[entityIDs addObject:value];

}

[entityIDs sortUsingSelector:@selector(compare:)];

// create the fetch request to get all Entities matching the IDs

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

[fetchRequest setEntity:entity];

NSString *filter = @"(%K IN %@)";

[fetchRequest setPredicate: [NSPredicate predicateWithFormat: filter, idName, entityIDs]];

// Make sure the results are sorted as well.

[fetchRequest setSortDescriptors:

@[ [[NSSortDescriptor alloc] initWithKey: idName ascending:YES] ]];

// Execute the fetch.

NSError *fetchError;

NSArray *entityMatchingNames = [self.elRehabCoreData.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];

int i = 0;

for (NSDictionary *keyedValues in jasonArrayData) {

i++;

//Create NSManagedObject

NSManagedObject *managedObject = nil;

//insert

managedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.elRehabCoreData.managedObjectContext];

//loop over entities in core data

for (NSString *attribute in entityAttributes) {

id value = [keyedValues objectForKey:attribute];

if (value == nil) {

// Don't attempt to set nil, or you'll overwite values in self that aren't present in keyedValues

continue;

}

NSAttributeType attributeType = [[entityAttributes objectForKey:attribute] attributeType];

if ((attributeType == NSStringAttributeType) && ([value isKindOfClass:[NSNumber class]])) {

value = [value stringValue];

} else if (((attributeType == NSInteger16AttributeType) || (attributeType == NSInteger32AttributeType) || (attributeType == NSInteger64AttributeType) || (attributeType == NSBooleanAttributeType)) && ([value isKindOfClass:[NSString class]])) {

value = [NSNumber numberWithInteger:[value integerValue]];

} else if ((attributeType == NSFloatAttributeType) && ([value isKindOfClass:[NSString class]])) {

value = [NSNumber numberWithDouble:[value doubleValue]];

}

/*Add values for valid attributes */

//set value

[managedObject setValue:value forKey:attribute];

}

}

//save core data stack

[self.elRehabCoreData saveContext];

NSLog(@"%@ and #managed objects are: %i ", @"Saved and Finished ", i);

}

网友答案:

I added an if condition like in http://www.raywenderlich.com/15916/how-to-synchronize-core-data-with-a-web-service-part-1 tutorial that checks if the count for the JSONArray is the same as that of the fetchedArray, then use the managedObject from the fetchedArray otherwise insert a new ManagedObject. This method is possible only if both arrays are sorted in exactly the same manner.

for (NSDictionary *keyedValues in sortedJSONArray) {


    //Create NSManagedObject
    NSManagedObject *managedObject = nil;
    int updateInsert = 0;

   //This is the part that determines whether to update or insert.
    if(entityMatchingNames.count > i ){
        managedObject = [entityMatchingNames objectAtIndex:i];
        NSLog(@"In Managed Object %@, In JSON %@", [managedObject valueForKey:idName], [keyedValues valueForKey:idName] );
        if ([[managedObject valueForKey:idName] isEqual:[NSNumber numberWithInteger:[[keyedValues valueForKey:idName] integerValue]]]) {

            updateInsert = 1;
        }

    }else{
        //insert
         managedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:self.elRehabCoreData.managedObjectContext];
            updateInsert = 1;
    }

    i++;

    //loop over entities in core data
    for (NSString *attribute in entityAttributes) {

        id value = [keyedValues objectForKey:attribute];

        if (value == nil) {
            // Don't attempt to set nil, or you'll overwite values in self that aren't present in keyedValues
            continue;
        }
        NSAttributeType attributeType = [[entityAttributes objectForKey:attribute] attributeType];

        if ((attributeType == NSStringAttributeType) && ([value isKindOfClass:[NSNumber class]])) {
            value = [value stringValue];
        } else if (((attributeType == NSInteger16AttributeType) || (attributeType == NSInteger32AttributeType) || (attributeType == NSInteger64AttributeType) || (attributeType == NSBooleanAttributeType)) && ([value isKindOfClass:[NSString class]])) {
            value = [NSNumber numberWithInteger:[value integerValue]];
        } else if ((attributeType == NSFloatAttributeType) &&  ([value isKindOfClass:[NSString class]])) {
            value = [NSNumber numberWithDouble:[value doubleValue]];
        }


        /*Add values for valid attributes */

        //set value
        if (updateInsert) {
            [managedObject setValue:value forKey:attribute];
        }




    }

}
分享给朋友:
您可能感兴趣的文章:
随机阅读: