开发者

How do I access data in a one-to-many relationship?

I only bought my first how-to-program book 2 months ago so I know this is probably pretty basic, but I am trying to learn how to use Core Data, and I cannot work out how to retrieve data from an object in a one-to-many relationship. I have spent all day googling and reading the Apple docs but cannot find a really simple explanation.

I have set up my core data model with the following entities:

"Trip" has one-to-many relationship from 'checklists' to…

"Checklist" has one-to-many relationship from 'checklistItems' to…

"ChecklistItem".

Then, in my App Delegate, in applicationDidFinishLaunching:, I have added the following simple code which just creates some managed objects and then displays them in the console:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    // Override point for customization after application launch.

    // TEST CORE DATA - MAKE OBJECTS
    NSManagedObjectContext *context = [self managedObjectContext];
    NSManagedObject *trip = [NSEntityDescription insertNewObjectForEntityForName:@"Trip" inManagedObjectContext:context];
    [trip setValue:@"Test Trip" forKey:@"tripName"];

    NSManagedObject *checklist = [NSEntityDescription insertNewObjectForEntityForName:@"Checklist" inManagedObjectContext:context];
    [checklist setValue:@"Test Checklist" forKey:@"checklistName"];


    NSManagedObject *checklistItem = [NSEntityDescription insertNewObjectForEntityForName:@"ChecklistItem" inManagedObjectContext:context];
    [checklistItem setValue:@"Test Checklist Item" forKey:@"checklistItemName"];
    [checklistItem setValue:[NSNumber numberWithBool:TRUE] forKey:@"checklistItemChecked"];
    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }

    // TEST CORE DATA - LIST OBJECTS
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"Trip" inManagedObjectContext:context]];

    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    for (NSManagedObject *info in fetchedObjects) {
        NSLog(@"Trip Name: %@", [info valueForKey:@"tripName"]);

        NSManagedObject *aChecklist = [info valueForKey:@"checklists"];
        NSLog(@"Checklist Name: %@", [aChecklist valueForKey:@"checklistName"]);

        NSManagedObject *aChecklistItem = [aChecklist valueForKey:@"checklistItems"];
        NSLog(@"Checklist Item Name: %@", [aChecklistItem valueForKey:@"checklistItemName"]);
        NSLog(@"Checklist Item Checked: %@", [aChecklistItem valueForKey:@"checklistItemChecked"] ? @"Yes it is!" : @"No It's Not!");
    }
    [fetchRequest release];

    [self.window makeKeyAndVisible];

    return YES;
}

When I run the program I get the following in the terminal:

2011-02-21 18:01:14.144 BYG[38204:207] Trip Name: Test Trip 2011-02-21 18:01:14.146 BYG[38204:207] Checklist Name: {( )} 2011-02-21 18:01:14.147 BYG[38204:207] Checklist Item Name: {( )} 2011-02-21 18:01:14.147 BYG[38204:207] Checklist Item Checked: Yes it is!

Two of the items, (Checklist Name and Checklist Item Name) just return empty brackets. I think I have a foggy understanding of why this is: those two attributes are in to-many relationships, so it does not know which checklist's name it is meant to be telling me. How do I go about getting values for these objects?

Sorry if this explanation is hazy. My brain has pretty-much shut down after a day of trying to work it out :)

-------------------------- EDIT ------

Thanks for the help! I have amended my code and it seems to work! I would appreciate it if you could tell me if this all looks good or if I'm making any rookie mistakes:

   - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    // Override point for customization after application launch.   
    // TEST CORE DATA - MAKE OBJECTS
    NSManagedObjectContext *context = [self managedObjectContext];

    Trip *newTrip = [Trip addEntityForContext:context];
    newTrip.tripName = @"Test Trip with addEntity"; 

    Checklist *newChecklist = [NSEntityDescription insertNewObjectForEntityForName:@"Checklist" inManagedObjectContext:context];
    [newTrip addChecklistsObject:newChecklist];
    newChecklist.checklistName = @"Test Checklist"; 

    ChecklistItem *newChecklistItem = [NSEntityDescription insertNewObjectForEntityForName:@"ChecklistItem" inManagedObjectContext:context];
    [newChecklist addChecklistItemsObject:newChecklistItem];
    newChecklistItem.checklistItemName = @"Test Checklist Item";
    newChecklistItem.checklistItemChecked = [NSNumber numberWithBool:TRUE];

    NSError *error;
    if (![context save:&error]) {
        NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
    }

    // TEST CORE DATA - LIST OBJECTS
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"Trip" inManagedObjectContext:context]];    
    NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
    for (Trip *info in fetchedObjects) {
        NSLog(@"Trip Name: %@", info.tripName);

        NSSet *aChecklistSet = [[NSSet alloc]initWithSet:info.checklists];
        Checklist *aChecklist = [aChecklistSet anyObject];
        NSLog(@"Checklist Name: %@", aChecklist.checklistName);

        NSSet *aChecklistItemSet = [[NSSet alloc]initWithSet:aChecklist.checklistItems];
        ChecklistItem *aChecklistItem = [aChecklistItemSet anyObject];
        NSLog(@"Checklist Item Name: %@", a开发者_如何学JAVAChecklistItem.checklistItemName);
        NSLog(@"Checklist Item Checked: %@", aChecklistItem.checklistItemChecked ? @"Yes it is!" : @"No It's Not!");
    }
    [fetchRequest release];

    [self.window makeKeyAndVisible];

    return YES;
}

(I haven't implemented addEntity yet as I wasn't sure how the model objects would get hold of the Context, but I think that's just a code-neatness thing so I'm not worrying about that yet).


You make it hard on yourself. You have to make (Model) Class. If you don't know model see:
MVC

You can do this to go to your coredatamodel, click in the model (not on Entity) and select new from the file menu. Here you can choose to make NSManagedObject subclasses. This will make classes for your selected entities.

These classes represent your core data objects.

Try to implement static methods in all classes like this:

+ (CheckListItem *) addEntity {
   return (CheckListItem *)[NSEntityDescription insertNewObjectForEntityForName:@"ChecklistItem" inManagedObjectContext:context];
}

For the context you can do two things. 1) Set the context from you application:didFinishLaunchingWithOptions: 2) Make singleton instance to hold your context. (Better solution)

You can now easily call from your application did finish launching:

CheckListItem *newItem = [CheckListItem addEntity];
CheckList *newList = [CheckList addEntity];

newItem.name = @"MyCheckListItemName";
newList.name = @"MyListName";

For the relation you can do:

newItem.checkList = newList;

Or:

[newList addCheckListItemsObject:newItem];
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜