Core Data to-one relationship returns NULL

757 views Asked by At

The Batting.team relationship doesn't always save properly and returns null sometimes

enter image description here

About 100 'Team' NSManagedObjects are saved and can log their attributes as expected. Then about 15000 'Batting' NSManagedObjects are saved and all attributes log correctly except for the relationship.

I want the Batting.team relationship to point to the Team object which has the same Team.teamID value as the Batting.teamID.

When setting the Batting relationship, I create a predicate to search for a specific Team.teamID, fetch the request and supposedly set that Team object to equal my Batting.team relationship. Sometimes the relationship attribute gets set but most times it doesn't and I can't figure this out

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    NSError *error;

    NSString* dataPath_TEAMS = [[NSBundle mainBundle] pathForResource:@"teams" ofType:@"json"];
    NSArray* TEAMS = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_TEAMS] options:kNilOptions error:&error];   

    NSString* dataPath_ABC = [[NSBundle mainBundle] pathForResource:@"abc" ofType:@"json"];
    NSArray* BATTING_ABC = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_ABC] options:kNilOptions error:&error];



    //insert Team objects
    NSFetchRequest *fetchRequestTeams = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityTeams = [NSEntityDescription entityForName:@"Team" inManagedObjectContext:self.managedObjectContext];
    [fetchRequestTeams setEntity:entityTeams];

    for (id t in TEAMS) {
        Team *team = [NSEntityDescription insertNewObjectForEntityForName:@"Team" inManagedObjectContext:self.managedObjectContext];

        team.name       = [t objectForKey:@"name"];
        team.minYearID  = [t objectForKey:@"minYearID"];
        team.maxYearID  = [t objectForKey:@"maxYearID"];
        team.teamID     = [t objectForKey:@"teamID"];

        if (![self.managedObjectContext save:&error]) {
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
        }
    }
    NSArray *fetchedObjectsTeams = [self.managedObjectContext executeFetchRequest:fetchRequestTeams error:&error];
    NSLog(@"Number of records in teams.json - %d", (int)[fetchedObjectsTeams count]);


    //insert Batting objects
    NSFetchRequest *fetchRequestBatting = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityBatting = [NSEntityDescription entityForName:@"Batting" inManagedObjectContext:self.managedObjectContext];
    [fetchRequestBatting setEntity:entityBatting];

    for (id b in BATTING_ABC) {
        Batting *batting = [NSEntityDescription insertNewObjectForEntityForName:@"Batting" inManagedObjectContext:self.managedObjectContext];

        batting.playerID    = [b objectForKey:@"playerID"];
        batting.h           = [b objectForKey:@"h"];
        batting.ab          = [b objectForKey:@"ab"];
        batting.hr          = [b objectForKey:@"hr"];
        batting.rbi         = [b objectForKey:@"rbi"];
        batting.sb          = [b objectForKey:@"sb"];
        batting.r           = [b objectForKey:@"r"];
        batting.bb          = [b objectForKey:@"bb"];
        batting.so          = [b objectForKey:@"so"];
        batting.yearID      = [b objectForKey:@"yearID"];
        batting.teamID      = [b objectForKey:@"teamID"];

        NSPredicate *teamIDPredicate = [NSPredicate predicateWithFormat:@"teamID == %@", [b objectForKey:@"teamID"]];
        [fetchRequestTeams setPredicate:teamIDPredicate];
        NSArray *fetchedSpecificTeam = [self.managedObjectContext executeFetchRequest:fetchRequestTeams error:&error];

        batting.team = [fetchedSpecificTeam firstObject];

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

    fetchedObjectsBatting = [self.managedObjectContext executeFetchRequest:fetchRequestBatting error:&error];
    for (Batting *b in fetchedObjectsBatting) {
        NSLog(@"playerID:   %@", b.playerID);
        NSLog(@"yearID:     %@", b.yearID);
        NSLog(@"teamID:     %@", b.teamID);
        NSLog(@"team:       %@\n\n", b.team.name);
    }

    return YES;
}

enter image description here

1

There are 1 answers

0
pbasdf On BEST ANSWER

From the screenshot of your model, it is configured so that each Team can have only one Batting. Each time you set batting.team to a given Team, CoreData will remove the link from that Team to its current Batting object (thereby setting that Batting object's team to nil).

You should define the Team entity's batting relationship to be "to-Many" (each Team can have many Battings) using the Data Model inspector on the right hand side when in the model editor:

enter image description here