核心数据关系:如何将新对象插入到实体中,并与另一个实体中的现有对象build立关系
我正在构build一个小的iPhone应用程序,它允许用户保持与朋友一起玩游戏的分数。 我现在需要在核心数据中使用关系,但似乎无法使其工作。
我希望能够将新数据添加到一个实体中,同时创build与另一个实体中现有数据的关系。 我怎样才能做到这一点?
请注意我是Core Data的新手,并且花费了今天最好的一部分来解决这个问题,但运气不佳。 任何帮助将非常感激。
我有3个实体: 分数 , 游戏和玩家 。
分数属性: date
, player1Score
, player2Score
和status
。
游戏属性: title
。
玩家属性: name
。
我有许多关系( 比赛 “—” 游戏 )和( 得分 << — >> 玩家 )
我已经有了一个游戏和玩家的列表。 用户select哪个游戏和谁在玩,并且利用这个信息,在Scores实体中创build了一组对象,并与所select的游戏和玩家有关系。
这是我的来源:
// 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];
你也必须改变你的关系“分数<< —”玩家“要下令,因为现在你不会知道哪个玩家是哪个。 其他的select是使用两个多对一的关系(分别为player1和player2)。
还有一件事:以单数forms命名实体是一种最佳做法,所以Score
,而不是Scores
等等。
您应该阅读创build托pipe对象关系 。 这里面都有很好的描述。
更新:我认为不应该有一个游戏和分数之间的多对多关系(从我所了解的分数可以重新命名为匹配)。 这可能应该是一个一对多的关系。
你可能会考虑重新devise你的对象图。 从现实来看,我的头脑中有一个概念,就是游戏,玩家和分数是如何相互关联的。 然而,你的对象图似乎并不符合这个概念(但你的游戏,玩家和分数如何相互关联的概念可能与我的不同)。
我会消除所有这些多对多的关系,并用一对多的关系来取代它们。 例如,玩家可以有很多分数,但分数不会有很多玩家。 三名球员可能有100分,但这并不意味着他们共享一个单一的得分对象(值为100)。
以下是我可能如何devise对象图:
游戏实体:
- 标题属性(例如“垄断”)
- 玩家关系,一对多(一个游戏,很多玩家)
玩家实体:
- 名字属性(例如,Joe Smith)
- 游戏关系,一对多(一个玩家,很多游戏)
- 分数关系,一对多(一名球员,很多分数)
得分实体:
- 分数属性,int值(例如100)
- 游戏关系,一对一(一个分数,一个游戏)
devise你的模型的另一种方法是如下所示:
游戏 – 代表游戏types的对象(垄断,网球等)
匹配 – 实际的“游戏”,发生在某个时间点,具有date/时间或时间段等属性。 加上player1,player2等…谁真正参加了。 加上每个球队或球员得分例如player1Score,player2Score …
竞争对手 – 或玩家。