我有一个对象,锻炼,它与一个对象,锻炼有一对多的关系。
模型图:http: //i.imgur.com/q1Mfq.png
当我创建一个锻炼对象时,我通过循环添加三个锻炼对象
[self addExercisesObject:exercise]
然后保存我的托管对象上下文。然后,从用于显示锻炼的控制器中,我可以成功获取锻炼及其锻炼(使用获取请求),如调试器中的输出所示:
Printing description of self->_savedWorkout:
<Workout: 0x6c5a990> (entity: Workout; id: 0x6e46e00 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Workout/p1> ; data: {
bodyweight = nil;
date = "2012-05-09 16:59:43 +0000";
exercises = (
"0x6e3c870 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Exercise/p3>",
"0x6e3eaf0 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Exercise/p2>",
"0x6e36820 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Exercise/p1>"
);
isCompleted = 0;
workoutId = 1;
workoutPlan = "0x6e6c980 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/WorkoutPlan/p1>";
})
到现在为止还挺好。但是,如果我在模拟器中关闭我的应用程序并重新启动它并在同一视图中执行相同的获取请求,则锻炼将如下所示:
Printing description of self->_savedWorkout:
<Workout: 0x6ea8ff0> (entity: Workout; id: 0x6e8f9e0 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/Workout/p1> ; data: {
bodyweight = nil;
date = "2012-05-09 16:59:43 +0000";
exercises = (
);
isCompleted = 0;
workoutId = 1;
workoutPlan = "0x6c8a130 <x-coredata://EA417EAA-101A-4F04-8276-3C4A6CDF094D/WorkoutPlan/p1>";
})
似乎它获取了相同的锻炼对象,但现在锻炼是一个空集。实际上,在 fetch 请求之后,练习首先看起来像这样:
exercises = "<relationship fault: 0x8a93100 'exercises'>";
但一旦我这样做:
for (Exercise *exercise in self.savedWorkout.exercises)
self.savedWorkout.exercises 解析为一个空集。我不会在我的应用程序的任何部分编辑锻炼。
我的获取请求是通过我的 Workout 类中的此方法发出的:
- (Workout *)getLatestWorkout
{
self.model = [[self.managedObjectContext persistentStoreCoordinator] managedObjectModel];
NSFetchRequest *fetchRequest = [self.model fetchRequestTemplateForName:@"getLatestWorkout"];
NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if ([results count] == 1) {
return [results objectAtIndex:0];
}
return nil;
}
我使用 Xcode 的 GUI 工具制作了获取请求模板。它获取 isCompleted == 0 的所有 Workout 对象。您可以看到它每次都获取相同的对象,因为在两个调试器输出中,锻炼的 x-coredata 路径是相同的。
更新:我检查了我的 SQLite 数据库。锻炼表中有一项锻炼,锻炼表中有三项锻炼。
有什么想法吗?
编辑:创建下面发布的对象的代码
- (void)storeUserSettings
{
// get the file path if it exists
NSString *path = [[NSBundle mainBundle] pathForResource:@"userSettings" ofType:@"plist"];
// create it if it doesn't
if (path == nil) {
path = [NSString stringWithFormat:@"%@%@",
[[NSBundle mainBundle] bundlePath], @"/userSettings.plist"];
}
// and write the new settings to file
[self.userSettings writeToFile:path atomically:YES];
// load managed object context
[self loadMOC];
WorkoutPlan *currentPlan = [[WorkoutPlan alloc] getActiveWorkoutPlan];
[currentPlan setManagedObjectContext:self.managedObjectContext];
// if user has no plan or is changing plans, create new plan and first workout
if (currentPlan == nil ||
([self.userSettings valueForKey:@"plan"] != currentPlan.planId)) {
// create a workoutPlan object
WorkoutPlan *workoutPlan = [[WorkoutPlan alloc] initWithEntity:
[NSEntityDescription entityForName:@"WorkoutPlan"
inManagedObjectContext:self.managedObjectContext]
insertIntoManagedObjectContext:self.managedObjectContext];
// set attributes to values from userSettings and save object
[workoutPlan createWorkoutPlanWithId:[self.userSettings valueForKey:@"plan"]
schedule:[self.userSettings valueForKey:@"schedule"]
dateStarted:[self.userSettings valueForKey:@"nextDate"]];
}
// if user is just changing schedule, update schedule of current plan
else if (![currentPlan.schedule isEqualToString:[self.userSettings valueForKey:@"schedule"]]) {
[currentPlan setSchedule:[self.userSettings valueForKey:@"schedule"]];
[currentPlan saveMOC];
}
}
- (void)loadMOC
{
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = delegate.managedObjectContext;
self.model = [[self.managedObjectContext persistentStoreCoordinator] managedObjectModel];
}
- (void)createWorkoutPlanWithId:(NSNumber *)planId schedule:(NSString *)schedule
dateStarted:(NSDate *)dateStarted
{
[self deactivateCurrentPlan];
// set workout plan attributes
[self setPlanId:planId];
[self setIsActive:[NSNumber numberWithBool:YES]];
[self setSchedule:schedule];
[self setDateStarted:dateStarted];
// create first workout and add to workout plan
Workout *firstWorkout = [NSEntityDescription
insertNewObjectForEntityForName:@"Workout"
inManagedObjectContext:self.managedObjectContext];
[firstWorkout setManagedObjectContext:self.managedObjectContext];
[firstWorkout createFirstWorkoutForPlan:self onDate:dateStarted];
[self addWorkoutsObject:firstWorkout];
[self saveMOC];
}
- (void)createFirstWorkoutForPlan:(WorkoutPlan *)plan onDate:(NSDate *)startDate
{
// set workout attributes
[self setDate:startDate];
[self setIsCompleted:[NSNumber numberWithBool:NO]];
[self setWorkoutId:[NSNumber numberWithInt:1]];
NSArray *exerciseList = [self getExercisesForWorkout:self inPlan:plan];
// iterate over exercises in spec and create them
for (NSDictionary *exerciseSpec in exerciseList)
{
// create a exercise MO
Exercise *exercise = [NSEntityDescription
insertNewObjectForEntityForName:@"Exercise"
inManagedObjectContext:[plan managedObjectContext]];
[exercise setManagedObjectContext:[plan managedObjectContext]];
[exercise createExerciseForWorkout:self withSpec:exerciseSpec];
// add exercise to workout object
[self addExercisesObject:exercise];
}
}
- (void)createExerciseForWorkout:(Workout *)workout withSpec:exerciseSpec
{
// set exercise attributes
self.exerciseId = [exerciseSpec valueForKey:@"id"];
self.isPersonalRecord = [NSNumber numberWithBool:NO];
NSArray *sets = [exerciseSpec valueForKey:@"sets"];
int i = 1;
for (NSNumber *setReps in sets)
{
// create a set MO
Set *set = [NSEntityDescription
insertNewObjectForEntityForName:@"Set"
inManagedObjectContext:[workout managedObjectContext]];
[set setManagedObjectContext:[workout managedObjectContext]];
// set set attributes
set.order = [NSNumber numberWithInt:i];
set.repetitions = setReps;
set.weight = [exerciseSpec valueForKey:@"default_weight"];
// add set to exercise object
[self addSetsObject:set];
i++;
}
}