核心数据关系:如何将新对象插入实体并创建与另一个实体中的现有对象的关系



我正在开发一个小的iPhone应用程序,允许用户保留他们可能与朋友一起玩的游戏的分数。我现在需要在核心数据中使用关系,但似乎无法让它正常工作。

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

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


我有 3 个实体:分数游戏玩家

分数属性:dateplayer1Scoreplayer2Scorestatus

游戏属性:title .

球员属性:name .

我在(比分<<--->>游戏(和(得分<<--->>玩家(之间有很多对多的关系


我已经有游戏和玩家的列表。用户选择哪个游戏和谁在玩,并根据此信息在 Score 实体中创建一组对象,其中包含与所选游戏和玩家的关系。

这是我的消息来源:

//  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

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

您必须将

Players ' 对象插入self.managedObjectContext与插入新Score对象完全相同。可能是这样的:

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

您还必须更改要排序的"玩家<<--->>分数"的关系,因为现在您不知道哪个玩家是哪个玩家。此处的其他选项是使用两个多对一关系(分别用于玩家 1 和玩家 2(。

还有一件事:最佳做法是以单数形式命名实体,因此Score,而不是Scores等等。

您应该阅读创建托管对象关系。这一切都在那里得到了很好的描述。

更新:我认为游戏和分数之间不应该有多对多关系(据我所知,分数可以重命名为匹配(。它可能应该是一对多的关系。

您可以考虑重新设计对象图。从现实中,我脑海中有一个概念,即游戏、玩家和分数如何相互关联。然而,你的对象图似乎与这个概念不符(但你对游戏、玩家和分数如何相互关联的概念可能与我的不同(。

我会消除所有这些多对多关系

,并用一对多关系取而代之。例如,一个玩家可以有很多分数,但一个分数不会有很多玩家。三个玩家的分数可能为 100,但这并不意味着他们共享一个分数对象(值为 100(。

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

游戏实体:

  • 标题属性(例如,"大富翁"(
  • 玩家
  • 关系,一对多(一个游戏,多个玩家(

玩家实体:

  • 名称属性(例如,乔·史密斯(
  • 游戏
  • 关系,一对多(一个玩家,多个游戏(
  • 分数
  • 关系,一对多(一个玩家,多个分数(

评分实体:

  • 分数属性,整数值(例如,100(
  • 游戏关系,一对一(一分一局(

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

游戏 - 是代表游戏类型(大富翁、网球等(

的对象

匹配 - 实际的"游戏",发生在某个时间点,并具有日期/时间或时间段等属性。加上玩家1,玩家2等...无论谁真正参与。加上每个球队或球员的得分,例如球员1得分,球员2得分...

竞争对手 - 或玩家。

最新更新