Reputation: 835
I have this One-to-Many
relationship
in Core Data
:
Each SBQChrono
can have many SBQLaps
.
In my model I have the class SBQLap
:
@interface CILap : NSObject
@property (strong, nonatomic) NSDate * lapDate;
@end
And the class SBQChrono
:
@interface CIChrono : NSObject
@property (strong, nonatomic) NSDate * startDate;
@property (strong, nonatomic) NSDate * stopDate;
@property (strong, nonatomic) NSOrderedSet *laps;
@end
I get all the SBQChrono
entities
doing:
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:kChronoEntityName];
NSError *error;
NSArray *objects = [appContext.managedObjectContext executeFetchRequest:request error:&error];
How can I get the specified SBQLap
entitys per each SBQChrono
I find? Ive read a lot of posts and cant get the solution.
UPDATE:
After trying to cast the NSManagedObject
, I realized that the laps is returned as nil value.
Doing:
for (NSManagedObject *oneObject in objects) {
CIChrono *chrono=(CIChrono *)oneObject;
NSLog(@"startDate %@", chrono.startDate);
NSLog(@"stopDate %@", chrono.stopDate);
NSLog(@"laps %@",chrono.laps);
} I get the message:
2014-01-28 14:39:48.379 Chrono[2341:70b] startDate 2014-01-28 12:27:53 +0000
2014-01-28 14:39:48.380 Chrono[2341:70b] stopDate 2014-01-28 12:27:54 +0000
2014-01-28 14:39:48.380 Chrono[2341:70b] -[NSManagedObject laps]: unrecognized selector sent to instance 0x8b959b0
2014-01-28 14:39:48.383 Chrono[2341:70b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject laps]: unrecognized selector sent to instance 0x8b959b0'
Thanks
Upvotes: 1
Views: 3658
Reputation: 12045
Looking at the model screenshot and code that you posted, it appears that the model has the relationship name set as lap
(singular) but your class definition is using laps
(plural). Core Data would be implementing an accessor for lap
, but doesn't understand laps
since it doesn't match the name in the model. Changing the model to say laps
should fix that problem.
Upvotes: 0
Reputation: 46718
Lots of interesting answers on this one.
The answer is very simple and does not require subclassing NSManagedObject
to access the objects in a relationship. You just need to use KVC (Key Value Coding) to access those objects. This is true of relationships and attributes.
If you want to use synthesized methods you can by subclassing as some have hinted at but that is not necessary.
Here is an extension to your example that you posted in your question:
for (NSManagedObject *oneObject in objects) {
CIChrono *chrono=(CIChrono *)oneObject;
NSLog(@"startDate %@", [chrono valueForKey:@"startDate");
NSLog(@"stopDate %@", [chrono valueForKey:@"stopDate"]);
NSLog(@"laps %@", [chrono valueForKey:@"laps"]);
NSSet *laps = [chrono valueForKey:@"laps"];
for (NSManagedObject *lap in laps) {
NSLog(@"Lap entity: %@", lap);
}
}
Note the -valueForKey:
calls. Those are Key Value Coding which NSManagedObject
instances (and all other Objective-C objects) respond to. I would suggest reading the documentation on KVC and KVO.
Upvotes: 6
Reputation: 402
You can fetch objects which have a relationship to 'SBQChrono'.
This can be done with two fetch requests, first fetch all the 'SBQChrono' objects & then perform a second request for 'SBQLap' entities with a predicate:
[NSPredicate predicateWithFormat:@"chrono IN %@",objects]
Upvotes: 0
Reputation: 6710
Each SQBChrono
object contains a set of SBQLap
objects that are associated with it. Look at your SQBChrono
properties
@property (strong, nonatomic) NSOrderedSet *laps;
laps
is a property that contains the many SBQLap
objects to one SQBChrono
object.
You can get an array from the set like this:
NSFetchRequest *request=[[NSFetchRequest alloc] initWithEntityName:kChronoEntityName];
NSError *error;
NSArray *chronoObjectArray = [appContext.managedObjectContext executeFetchRequest:request error:&error];
for (SQBChrono * chrono in chronoObjectArray) {
NSArray *lapsArray = [chrono.laps array];
NSLog("Chrono: %@ laps: %@", chrono.startDate, lapsArray);
}
Upvotes: 2
Reputation: 3456
Your array objects contains all your SBQChrono objects.
You can get all the SBQLaps associated with one chrono by doing:
SQBChrono * myChrono = objects[indexOfTheDesiredChrono];
The laps of the chrono are then in myChrono.laps, which is a NSOrderedSet (collection) of SBQLaps. Can be turn into an array like this :
NSArray * myChronoLaps = [myChrono.laps array]
Upvotes: 0
Reputation: 5681
As you've added the SBQChrono objects to an array you will need to cast it:
SQBChrono *anObject = (SQBChrono *)objects[0];
Then you can:
anObject.laps;
Will give you the NSSet of all associated objects ?
Upvotes: 0