【问题标题】:Core Data Relationships: How to insert a new object into an entity and create a relationship to an existing object in another entity核心数据关系:如何将新对象插入实体并创建与另一个实体中现有对象的关系
【发布时间】:2013-10-18 15:27:04
【问题描述】:

我正在构建一个小的 iPhone 应用程序,它允许用户记录他们可能与朋友一起玩的游戏的分数。我现在需要在 Core Data 中使用关系,但似乎不能让它正常工作。

我希望能够将新数据添加到一个实体中,同时创建与不同实体中现有数据的关系。我怎样才能做到这一点?

请注意,我是 Core Data 的新手,今天大部分时间都在试图解决这个问题,但运气不佳。任何帮助将不胜感激。


我有 3 个实体:ScoresGamesPlayers

分数属性:dateplayer1Scoreplayer2Scorestatus

游戏属性:title

玩家属性:name

我在 (Scores > Games) 和 (Scores > 玩家)


我已经有了游戏和玩家的列表。用户选择哪个游戏和谁在玩,并使用此信息在 Scores 实体中创建一组对象,这些对象与所选游戏和玩家有关系。

这是我的来源:

//  Scores.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Games, Players;

@interface Scores : NSManagedObject

@property (nonatomic, retain) NSDate * date;
@property (nonatomic, retain) NSNumber * player1Score;
@property (nonatomic, retain) NSNumber * player2Score;
@property (nonatomic, retain) NSNumber * status;
@property (nonatomic, retain) NSSet *game;
@property (nonatomic, retain) NSSet *player;
@end

@interface Scores (CoreDataGeneratedAccessors)

- (void)addGameObject:(Games *)value;
- (void)removeGameObject:(Games *)value;
- (void)addGame:(NSSet *)values;
- (void)removeGame:(NSSet *)values;

- (void)addPlayerObject:(Players *)value;
- (void)removePlayerObject:(Players *)value;
- (void)addPlayer:(NSSet *)values;
- (void)removePlayer:(NSSet *)values;

@end

// SC_ScoreViewController.h

#import <UIKit/UIKit.h>

@interface SC_ScoreViewController : UIViewController

@property (strong) NSIndexPath *game;
@property (strong) NSIndexPath *playerOne;
@property (strong) NSIndexPath *playerTwo;

@property (weak, nonatomic) IBOutlet UILabel *playerOneName;
@property (weak, nonatomic) IBOutlet UILabel *playerTwoName;

@end

//  SC_ScoreViewController.m

#import "SC_ScoreViewController.h"
#import "Scores.h"
#import "Players.h"
#import "Games.h"

@interface SC_ScoreViewController ()

@end

@implementation SC_ScoreViewController

@synthesize game;
@synthesize playerOne;
@synthesize playerTwo;

// managedObjectContext (context)
- (NSManagedObjectContext *)managedObjectContext {
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
if ([delegate respondsToSelector:@selector(managedObjectContext)]) {
        context = [delegate managedObjectContext];
    }
    return context;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Setup Nav Title
    self.navigationItem.title = [self.game valueForKey:@"title"];

    // Setup Player's Names
    [self.playerOneName setText:[self.playerOne valueForKey:@"name"]];
    [self.playerTwoName setText:[self.playerTwo valueForKey:@"name"]];


    Scores * newEntry = [NSEntityDescription insertNewObjectForEntityForName:@"Scores"        inManagedObjectContext:self.managedObjectContext];
    newEntry.player1Score = 0;
    newEntry.player2Score = 0;
    newEntry.status = nil;
    newEntry.player = self.playerOne; // Incompatible pointer types assigning to NSSet from NSIndexPath

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

    - (void)didReceiveMemoryWarning
    {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

    @end

我希望我已经清楚并提供了足够的信息。这是我的第一个问题,所以我希望一切顺利。任何帮助都会很棒,谢谢。

【问题讨论】:

    标签: iphone ios objective-c xcode core-data


    【解决方案1】:

    您必须将 Players' 对象插入到 self.managedObjectContext 中,就像插入新的 Score 对象一样。可能是这样的:

    Scores *score = [NSEntityDescription insertNewObjectForEntityForName:@"Scores" inManagedObjectContext:self.managedObjectContext];
    Player *player = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:self.managedObjectContext];
    [score addPlayerObject:player];
    

    您还必须更改您的关系“分数 > 玩家”以进行排序,因为现在您不知道哪个玩家是哪个玩家。此处的其他选项是使用两个多对一关系(分别用于 player1 和 player2)。

    还有一点:最好以单数形式命名您的实体,例如 Score,而不是 Scores 等等。

    您应该阅读Creating Managed Object Relationships。里面的描述都很好。

    更新:我认为游戏和分数之间不应该存在多对多的关系(据我了解,分数可以重命名为匹配)。应该是一对多的关系。

    【讨论】:

    • 您好,感谢您这么快回答。如果您不介意,我有几个后续问题。查看您的代码,将与分数一起创建一个新玩家,对吗?如果是这样,我的问题是我已经有球员并希望将他们与得分联系起来,否则我只是在重新创建他们。此外,我还有多对多的关系,因为分数可以有多个游戏,游戏也可以有多个分数,玩家和分数也是如此。
    • 对不起,我没有完全理解你的数据模型(你的关系)。至于玩家,我看到你有self.playerOneself.playerOneName。它们分别是:NSIndexPathUILabel。当您对 Core Data 关系进行操作时,您必须使用 NSManagedObject's 。我假设你还没有它们(因为它们不存在于你的视图控制器中),这就是为什么我创建了一个新的播放器:'Player *player = [NSEntityDescription (...)'。跨度>
    • 我尝试过使用 NSManagedObject 但无法正常工作。我不断收到错误“从 NSManageObject 分配给 NSSet 的指针类型不兼容”。我觉得我在这里遗漏了一些东西,我需要哪一行代码来创建从分数到玩家的关系?我应该为每个玩家使用两个独立的关系吗?
    • 您收到此错误,因为 addPlayer: 需要 NSSet,但您尝试分配给它 NSManagedObjectaddPlayerObject: 需要一个 NSManagedObject。正如我在回答中所写的那样,您可以将关系更改为有序(然后您将获得@property (nonatomic, retain) NSOrderedSet *players;)或使用两个多对一关系。
    【解决方案2】:

    您可能会考虑重新设计您的对象图。从现实来看,我对游戏、玩家和分数如何相互关联有一个概念。但是,您的对象图似乎与该概念不匹配(但您对游戏、玩家和分数如何相互关联的概念可能与我的不同)。

    我会消除所有这些多对多关系并用一对多关系代替它们。例如,一个玩家可以有很多分数,但一个分数不会有很多玩家。三个玩家的分数可能为 100,但这并不意味着他们共享一个分数对象(值为 100)。

    以下是我设计对象图的方式:

    游戏实体:

    • 标题属性(例如,“垄断”)
    • 玩家关系,一对多(一个游戏,多个玩家)

    玩家实体:

    • 姓名属性(例如,Joe Smith)
    • 游戏关系,一对多(一个玩家,多个游戏)
    • 分数关系,一对多(一个玩家,多个分数)

    分数实体:

    • score 属性,int 值(例如,100)
    • 游戏关系,一对一(一分一局)

    【讨论】:

      【解决方案3】:

      设计模型时的另一种思考方式如下:

      Game - 是表示游戏类型(垄断、网球等)的对象

      比赛 - 实际的“比赛”,发生在某个时间点,并具有日期/时间或期间等属性。再加上 player1、player2 等……无论谁实际参与。加上每支球队或球员的得分,例如player1Score, player2Score...

      竞争对手 - 或玩家。

      【讨论】:

        猜你喜欢
        • 2015-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-13
        • 1970-01-01
        • 2023-04-06
        • 1970-01-01
        相关资源
        最近更新 更多