在将数据添加到具有一对多关系的核心数据模型时遇到一些麻烦。
以下是我的模特:
RecordDate - Relationship: records - One to Many with RecordWorkout.
RecordWorkout - Relationship: recExercises - One to Many With RecordExercise.
RecordExercise - Relationship: sets - One to Many With RecordSet.
RecordSet
RecordDate包含单个字符串变量日期。 (不存储重复的日期变量)
RecordWorkout包含单个字符串变量recWorkoutName。 (不能存储recWorkoutName的重复变量。)
RecordExercise包含单个字符串变量recExerciseName。 (也不能存储recExerciseName的重复变量。
RecordSet包含三个字符串变量(setLog,weight,reps)。 (同样,不能为setLog变量存储重复变量。
代码目标:
目标是单击一个按钮(日志按钮),单击“按钮”时,代码需要将屏幕上的值与数据存储中已有的值进行比较,这样就不会存储重复值。
示例:
日期> workoutName>运动> (许多集合例如:set1,set2,set3,set4)
首次点击按钮日期时,会存储workoutName exerciseName和第一组详细信息。在第二次点击时,只存储新的设定数据。
下面是我正在使用的代码,但它似乎没有存储所有设置值,有些集会从数据存储中丢失或只存储第一个集。
setCount = setCount + 1;
NSString *weight = weightTextField.text;
NSString *reps = repsTextField.text;
NSString *setStr = [NSString stringWithFormat:@"%d", (int)setCount];
NSMutableString *log = [NSMutableString stringWithFormat:@"%@ %@%@ %@ %@ %@ %@", @"Set", setStr, @":", weight, @"kg X", reps, @"reps"];
[self.tempLog addObject:log];
[self.myTableView reloadData];
[weightTextField resignFirstResponder];
[repsTextField resignFirstResponder];
//the set is stored in a temporary mutable array (tempLog) just to show in tableview
//i would rather just store it in the actual entity and fetch from there
//Entities are initialised below
NSEntityDescription *recordDateEntity = [NSEntityDescription entityForName:@"RecordDate"
inManagedObjectContext:self.managedObjectContext];
NSEntityDescription *recordWorkoutEntity = [NSEntityDescription entityForName:@"RecordWorkout"
inManagedObjectContext:self.managedObjectContext];
NSEntityDescription *recordExerciseEntity = [NSEntityDescription entityForName:@"RecordExercise"
inManagedObjectContext:self.managedObjectContext];
NSEntityDescription *recordSetEntity = [NSEntityDescription entityForName:@"RecordSet" inManagedObjectContext:self.managedObjectContext];
//Data is fetched from the existing store to be compared with the data on screen
//This data is stored in mutable arrays (record date, recordworkouts, recordexercises, recordsets)
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"RecordDate"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"date == %@", dateLabel.text];
[fetchRequest setPredicate:predicate];
self.recorddates = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
NSFetchRequest *fetchRWRequest = [[NSFetchRequest alloc] initWithEntityName:@"RecordWorkout"];
NSPredicate *predicateRW = [NSPredicate predicateWithFormat:@"recWorkoutName == %@", testLabel2.text];
[fetchRWRequest setPredicate:predicateRW];
self.recordworkouts = [[managedObjectContext executeFetchRequest:fetchRWRequest error:nil] mutableCopy];
NSFetchRequest *fetchRERequest = [[NSFetchRequest alloc] initWithEntityName:@"RecordExercise"];
NSPredicate *predicateRE = [NSPredicate predicateWithFormat:@"recExerciseName == %@", exNameLabel.text];
[fetchRERequest setPredicate:predicateRE];
self.recordexercises = [[managedObjectContext executeFetchRequest:fetchRERequest error:nil] mutableCopy];
NSFetchRequest *fetchRSetRequest = [[NSFetchRequest alloc] initWithEntityName:@"RecordSet"];
NSPredicate *predicateRSet = [NSPredicate predicateWithFormat:@"setLog == %@", setStr];
[fetchRSetRequest setPredicate:predicateRSet];
self.recordsets = [[managedObjectContext executeFetchRequest:fetchRSetRequest error:nil] mutableCopy];
if ([self.recorddates count] == 0) {
NSLog(@"No Dates Imported");
RecordDate *newRecordDate = (RecordDate *)[[NSManagedObject alloc]
initWithEntity:recordDateEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordDate.date = dateLabel.text;
RecordWorkout *newRecordWorkout = (RecordWorkout *)[[NSManagedObject alloc]
initWithEntity:recordWorkoutEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordWorkout.recWorkoutName = testLabel2.text;
[newRecordDate addRecordsObject:newRecordWorkout];
RecordExercise *newRecordExercise = (RecordExercise *)[[NSManagedObject alloc] initWithEntity:recordExerciseEntity insertIntoManagedObjectContext:self.managedObjectContext];
newRecordExercise.recExerciseName = exNameLabel.text;
[newRecordWorkout addRecExercisesObject:newRecordExercise];
RecordSet *newRecordSet = (RecordSet *)[[NSManagedObject alloc]
initWithEntity:recordSetEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordSet.setLog = setStr;
newRecordSet.weight = weight;
newRecordSet.reps = reps;
[newRecordExercise addSetsObject:newRecordSet];
NSLog(@"Set number one should be added to model: %@", setStr);
} else {
NSLog(@"Dates Are Imported");
RecordDate *prevRecordDate = (RecordDate *)[self.recorddates objectAtIndex:0];
if ([self.recordworkouts count] == 0) {
RecordWorkout *newRecordWorkout = (RecordWorkout *)[[NSManagedObject alloc]
initWithEntity:recordWorkoutEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordWorkout.recWorkoutName = testLabel2.text;
[prevRecordDate addRecordsObject:newRecordWorkout];
RecordExercise *newRecordExercise = (RecordExercise *)[[NSManagedObject alloc] initWithEntity:recordExerciseEntity insertIntoManagedObjectContext:self.managedObjectContext];
newRecordExercise.recExerciseName = exNameLabel.text;
[newRecordWorkout addRecExercisesObject:newRecordExercise];
RecordSet *newRecordSet = (RecordSet *)[[NSManagedObject alloc]
initWithEntity:recordSetEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordSet.setLog = setStr;
newRecordSet.weight = weight;
newRecordSet.reps = reps;
[newRecordExercise addSetsObject:newRecordSet];
} else {
RecordWorkout *prevRecordWorkout = [self.recordworkouts objectAtIndex:0];
if ([self.recordexercises count] == 0) {
RecordExercise *newRecordExercise = (RecordExercise *)[[NSManagedObject alloc] initWithEntity:recordExerciseEntity insertIntoManagedObjectContext:self.managedObjectContext];
newRecordExercise.recExerciseName = exNameLabel.text;
[prevRecordWorkout addRecExercisesObject:newRecordExercise];
RecordSet *newRecordSet = (RecordSet *)[[NSManagedObject alloc]
initWithEntity:recordSetEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordSet.setLog = setStr;
newRecordSet.weight = weight;
newRecordSet.reps = reps;
[newRecordExercise addSetsObject:newRecordSet];
} else {
RecordExercise *prevRecordExercise = [self.recordexercises objectAtIndex:0];
if ([self.recordsets count] == 0) {
RecordSet *newRecordSet = (RecordSet *)[[NSManagedObject alloc]
initWithEntity:recordSetEntity
insertIntoManagedObjectContext:self.managedObjectContext];
newRecordSet.setLog = setStr;
newRecordSet.weight = weight;
newRecordSet.reps = reps;
[prevRecordExercise addSetsObject:newRecordSet];
} else {
NSLog(@"Sets Already Imported");
}
}
}
NSError *errr;
if (![self.managedObjectContext save:&errr])
{
NSLog(@"Error saving context: %@", errr);
}
}
我觉得在使用更好的组织代码之后我可以实现我的目标。
感谢您提供的任何帮助。
PS。上面的代码在logButtonPressed方法
中答案 0 :(得分:1)
它可以简单得多。
1)对于提取,仅提取日期并让Core Data负责获取其他内容就足够了。效率更高,代码更少。要“获取”相关实体:
NSSet *workouts = date.workouts;
NSSet *exercises = aWorkout.exercises;
NSSet *sets = anExercise.sets;
2)用于检查项目是否存在,例如日期只是遵循这种模式:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Date"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"%K = %@", attributeName, theDateStringToBeChecked];
request.fetchLimit = 1;
NSArray *dates = [self.managedObjectContext executeFetchRequest:request];
NSManagedObject *objectToUse = dates.count ? dates[0] : [NSEntityDescription
insertNewObjectForEntityName:"Date"
inManagedObjectContext:self.managedObjectContext];
通过构造一个获取实体字符串,属性字符串和要检查的值的方法,可以大大减少代码。它会有这样的原型:
-(NSManagedObject*)existingOrNewObjectWithEntityName:(NSString*)name
attribute:(NSString*)attribute value:(NSString*)value;
因为您的对象是NSManagedObject
的子类,所以您可以简单地将它们转换为正确的类型。
最后,不要忘记致电[self.managedObjectContext save:&error];
来保留您的更改。