0

I'm new in use Core Data. I have a two entities CDContact and CDAddress. I have problem to fetch a second entity (CDAddress).

self.fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"CDContact"];
[self.fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES]]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:self.fetchRequest managedObjectContext:[CoreDataManager sharedInstance].managedObjectContext sectionNameKeyPath:nil cacheName:nil];

[self.fetchedResultsController setDelegate:self];
[self fetchResults];

It works but I get only data from CDContact.

I try something like this (I found this on documentation):

NSManagedObjectContext *context = [CoreDataManager sharedInstance].managedObjectContext;
NSEntityDescription *contactEntity = [NSEntityDescription entityForName:@"CDContact" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = contactEntity;
request.relationshipKeyPathsForPrefetching = [NSArray arrayWithObject:@"CDAddress"];

but in this version both entities doesn't work.

I'll be glad for any examples which help me resolve this problem.

4
  • Have you defined a relationship between those two entities? Commented Sep 7, 2015 at 19:44
  • yes, I defined one-to-one relationship in .xdatamodeld file Commented Sep 7, 2015 at 19:57
  • A fetch will only return results from a single entity. To access the second entity, you either need to run a second fetch, or to use the relationship on your CDContact objects. For example if the relationship is named "address", myCDContact.address will give the CDAddress for the specified CDContact. Commented Sep 7, 2015 at 23:04
  • can you give me example code how to make this relationship? I will be glad for this Commented Sep 8, 2015 at 8:09

2 Answers 2

1

As per comments, a fetch will only return results from a single entity. To access the second entity, you either need to run a second fetch, or to use the relationship on your CDContact objects. For example if the relationship is named address,

myCDContact.address

will give the CDAddress for the specified CDContact.

To expand on this, suppose your CDContact entity has attributes firstName and lastName, and a one-one relationship to CDAddress entitled address. Likewise suppose your CDAddress entity has attributes street, town, and zipCode, and the inverse relationship to CDContact entitled contact.

Then to create a new contact named "John Smith" living at "1 Main Street, AnyTown, 90210", you would have code something like this:

CDContact *myCDContact = (CDContact *)[NSEntityDescription insertNewObjectForEntityForName:@"CDContact" inManagedObjectContext:context];
myCDContact.firstName = @"John";
myCDContact.lastName = @"Smith";
CDAddress *myCDAddress = (CDAddress *)[NSEntityDescription insertNewObjectForEntityForName:@"CDAddress" inManagedObjectContext:context];
myCDAddress.street = @"1 Main Street";
myCDAddress.town = @"AnyTown";
myCDAddress.zipCode = @"90210";
// and lastly, to set the relationship between them...
// EITHER
myCDContact.address = myCDAddress;
// OR
myCDAddress.contact = myCDContact;

(Note the either/or: you only have to set the relationship "one-way", CoreData will set the inverse automatically). If you then save the context, and subsequently fetch the contacts, with something like this:

NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"CDContact"];
[fetch setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES]]];
NSError *error;
NSArray *results = [context executeFetchRequest:fetch error:&error];

then (assuming the fetch is successful: you should test for nil/error) the array will contain your contacts. Taking the first item in the array, you can then access its properties including the related CDAddress like this:

CDContact *myContact = (CDContact *)[results objectAtIndex:0];
NSLog(@"The contact is %@ %@", myContact.firstName, myContact.lastName);
NSLog(@"who lives at %@, %@, %@", myContact.address.street, myContact.address.town, myContact.address.zipCode);

(All the above assumes you have created NSManagedObject subclasses for your entities. If you haven't, you should.)

Sign up to request clarification or add additional context in comments.

Comments

0

The answer provided by pbasdf is perfect and very detailed. However, I would like to add this from the apple documentation.

To retrieve data using a managed object context, you create a fetch request. A fetch request is an object that specifies what data you want, for example, “all Employees,” or “all Employees in the Marketing department ordered by salary, highest to lowest.” A fetch request has three parts. Minimally it must specify the name of an entity (by implication, you can only fetch one type of entity at a time). It may also contain a predicate object that specifies conditions that objects must match and an array of sort descriptor objects that specifies the order in which the objects should appear...

Assuming the relationship between the entities CDContact and CDAddress is one-to-one, your CDContact interface file should look something like this:

@interface CDContact : NSManagedObject

@property (nonatomic,strong) NSString *firstName;
@property (nonatomic,strong) NSString *lastName;
@property (nonatomic,strong) CDAddress *address;

@end

This way, once you fetch a given CDContact object, you can access the related CDAddress object using the property "address". But if you need to access all addresses and all contacts, you need to perform two separate fetches.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.