如何访问一对多关系中的数据?

发布于 2024-10-18 10:49:45 字数 5282 浏览 8 评论 0原文

我两个月前才买了第一本如何编程的书,所以我知道这可能非常基础,但我正在尝试学习如何使用核心数据,但我无法弄清楚如何从一个对象中检索数据一对多关系。我花了一整天的时间在谷歌上搜索并阅读苹果文档,但找不到真正简单的解释。

我已经使用以下实体设置了核心数据模型:

“Trip”具有从“checklists”到...“Checklist”的一对多关系,

“Checklist”具有从“checklistItems”到...“ChecklistItem”的一对多关系

然后,在我的应用程序委托中,在 applicationDidFinishLaunching: 中,我添加了以下简单代码,该代码仅创建一些托管对象,然后将它们显示在控制台中:

    - (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;
}

当我运行程序时,我在终端中收到以下内容:

2011-02-21 18:01:14.144 BYG[38204:207] 行程名称:测试行程 2011-02-21 18:01:14.146 BYG[38204:207] 清单名称:{( )} 2011-02-21 18:01:14.147 BYG[38204:207] 清单项目名称:{( )} 2011-02-21 18:01:14.147 BYG[38204:207] 检查清单项目:是的!

其中两项(清单名称和清单项目名称)仅返回空括号。我想我对为什么会这样有一个模糊的理解:这两个属性处于一对多关系中,所以它不知道它要告诉我的是哪个清单的名称。我如何获取这些对象的值?

抱歉,如果这个解释含糊不清。经过一天的尝试后,我的大脑几乎已经关闭了:)

-------------------------- 编辑 ---- ——

感谢您的帮助!我修改了我的代码,它似乎有效!如果您能告诉我这一切是否看起来不错或者我是否犯了任何菜鸟错误,我将不胜感激:(

   - (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: %@", aChecklistItem.checklistItemName);
        NSLog(@"Checklist Item Checked: %@", aChecklistItem.checklistItemChecked ? @"Yes it is!" : @"No It's Not!");
    }
    [fetchRequest release];

    [self.window makeKeyAndVisible];

    return YES;
}

我还没有实现 addEntity 因为我不确定模型对象如何获取上下文,但是我认为这只是代码整洁的事情,所以我还不担心这一点)。

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: %@", aChecklistItem.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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

飘逸的'云 2024-10-25 10:49:45

你让自己很难受。你必须制作(模型)类。如果您不知道模型,请参阅:
MVC

您可以执行此操作以转到核心数据模型,单击模型(而不是实体),然后从文件菜单中选择“新建”。这里你可以选择创建NSManagedObject子类。这将为您选择的实体创建类。

这些类代表您的核心数据对象。

尝试在所有类中实现静态方法,如下所示:

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

对于上下文,您可以做两件事。
1)设置应用程序的上下文:didFinishLaunchingWithOptions:
2)创建单例实例来保存您的上下文。 (更好的解决方案)

您现在可以轻松地从应用程序完成启动后调用:

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

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

对于您可以执行的关系:

newItem.checkList = newList;

或者:

[newList addCheckListItemsObject:newItem];

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];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文