I am building a little iPhone app which allows users to keep score of games they may be playing with friends. I now need to use relationships in Core Data but can't quite seem to get it working.
I want to be able to add new data into one entity while creating a relationship to existing data in a different entity. How can I achieve this?
Please note I am new to Core Data and have spent the best part of today trying to figure this out but have run out of luck. Any help would be very much appreciated.
I have 3 entities: Scores, Games and Players.
Scores Attributes: date
, player1Score
, player2Score
and status
.
Games Attributes: title
.
Players Attributes: name
.
I have many to many relationships between (Scores <<--->> Games) and (Scores <<--->> Players)
I already have a list of both games and players. The user selects which game and who is playing and with this information a set of objects is created in the Scores entity with relationships to the chosen game and players.
Here is my source:
// 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
I hope I have been clear and provided enough information. This is my first question so I hope all is in order. Any help would be amazing, thank you.
You have to insert Players
' objects into self.managedObjectContext
exactly the same as you insert a new Score
object. It could be something like this:
Scores *score = [NSEntityDescription insertNewObjectForEntityForName:@"Scores" inManagedObjectContext:self.managedObjectContext];
Player *player = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:self.managedObjectContext];
[score addPlayerObject:player];
You also have to change your relationship "Scores <<--->> Players" to be ordered, because right now you won't know which player is which. Other option here would be to use two many-to-one relationship (separately for player1 and player2).
One more thing: it's a best practice to name your entities in a singular form, so Score
, instead of Scores
and so on.
You should read Creating Managed Object Relationships. It's all nicely described in there.
UPDATE: I think there shouldn't be a many-to-many relationship between Games and Scores (from what I understand Score can be renamed to Match). It probably should be a one-to-many relationship.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With