How to add coreData relationships in objective c - core-data

I need to set relationships for cards and note, below is the sample code
Cards:
AppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
entityObj = [NSEntityDescription insertNewObjectForEntityForName:#"Customer" inManagedObjectContext:_appDel.managedObjectContext];
[entityObj setValue: userName forKey:#"custname"];
[entityObj setValue: userDesignation forKey:#"custdesignation"];
[entityObj setValue: userComapnay forKey:#"custcompany"];
[AppDelegate saveContxt];
Notes:
AppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
entityObj = [NSEntityDescription insertNewObjectForEntityForName:#"Notes" inManagedObjectContext:_appDel.managedObjectContext];
[entityObj setValue: userName forKey:#"notes"];
[entityObj setValue: userDesignation forKey:#"date"];
[AppDelegate saveContxt];
How to set relationship for above two models?

First, core data is not a database. Don't treat it like one. It's a persistent object graph.
How do you usually make relations between core data objects? This is no different than any other relationship. I assume there’s a 1:n relation, where one user can have multiple notes? You just model that relationship in core data and add the created note to the notes array of the user.
Read a tutorial about relationships in core data. This seems similar to what you want to achieve: https://hackernoon.com/core-data-relationships-d813ed66ba8c

Related

FetchRequest and NSPredicate issue

I have a 4 Entity One to Many relationship.
Having problem with the fetch and predicates. I am able to fetch the correct 1st entity data (RecordDate) . i use this object self.recordDate. to then fetch the many RecordWorkouts.
my code is below:
self.recordDate = [self.recorddates objectAtIndex:0];
NSLog(#"Date: %#", self.recordDate.date);
NSFetchRequest *fetchWorkoutRequest = [[NSFetchRequest alloc] initWithEntityName:#"RecordWorkout"];
NSPredicate *predicateWorkout = [NSPredicate predicateWithFormat:#"recordDate = %#", self.recordDate];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"recWorkoutName" ascending:YES];
[fetchWorkoutRequest setSortDescriptors:#[sortDescriptor]];
[fetchWorkoutRequest setPredicate:predicateWorkout];
self.recordworkouts = [[managedObjectContext executeFetchRequest:fetchWorkoutRequest error:nil] mutableCopy];
self.recordWorkout = [self.recordworkouts objectAtIndex:0];
NSLog(#"Workout: %#", self.recordWorkout.recWorkoutName);
I manage to fetch the RecordWorkout associated with the RecordDate Entity. This works fine for when there is only one object stored in RecordWorkout.
But When there is more than one stored in RecordWorkout It will fetch them all.
Is it possible to add a secondary NSPredicate within this fetch to for example only fetch the recordWorkout that is equal to workoutLabel.text.
Thanks
Answer for anyone who may need it.
Within Predicate you can have two requests:
NSPredicate *predicateWorkout = [NSPredicate predicateWithFormat:#"recordDate = %# AND recWorkoutName == %#", self.recordDate, testLabel2.text];

CoreData Fetch Predicate for unrelated entities

I am having trouble to do a CoreData fetch request for unrelated entities. Lets assume I have an object model with 3 entities: Message, User and Advisor.
I want this 3 objects to be unrelated to each other. So a Message does have an attribute senderEmail and receiverEmail whilst User and Advisor do have the attribute email.
But again, there is no further relationship between those objects.
I now want for example to fetch the latest (newst) Message by an advisor or by a user. But how should I do this fetch predicate since the objects are not connected?
Is this even possible within one Fetch Request or do I need to fetch each objects separately into an array and then make further operations to get what I want?
Alexander,
if those entities are not related each other you need to excecute different fetch requests to grab your data.
So, for example, you could grab the latest Message setting up a request like the following:
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"senderEmail == %#", grabbedEmail];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"insertionDate" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSFetchRequest *messageFetch = [[NSFetchRequest alloc] init];
[messageFetch setEntity:[NSEntityDescription entityForName:#"Message" inManagedObjectContext:yourContext]];
[messageFetch setPredicate:predicate];
[messageFetch setSortDescriptors:sortDescriptors];
[messageFetch setFetchLimit:1];
To retrieve the grabbedEmail (if you don't have it) you need to set up a request with a specific predicate. The same could be applied for the receiver email. For example.
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"userId == %#", #"someUserId"];
NSFetchRequest* userFetch = [[NSFetchRequest alloc] init];
[userFetch setEntity:[NSEntityDescription entityForName:#"User" inManagedObjectContext:yourContext]];
[userFetch setPredicate:predicate];
[userFetch setFetchLimit:1];
NSArray* userResults = [userFetch executeFetchRequest:&error];
User* retrievedUser = (User*)[userResults objectAtIndex:0];
NSString* grabbedEmail = [retrievedUser email];
To sort by date you could simply add to Message enitity an attribute called insertionDate (of type NSDate) that allows you to order by date.
When you execute the request
NSArray* results = [messageFetch executeFetchRequest:&error];
the array results will contain the (only) Message element you are looking for.
Why do you need to maintain separate those entities?
Hope that helps.

iOS Core Data how to properly initialize entity relationships?

I have a one to many relationship in my core data model. I need to create a new entity and save it. The entity has a one to many relationship which generated the following code:
- (void)addRelationshipEvent1:(NSSet *)values;
- (void)removeRelationshipEvent1:(NSSet *)values;
.
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
ApplicationRecord *newManagedObject = (ApplicationRecord*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
newManagedObject.startDate = [NSDate date];
newManagedObject.stopDate = [[NSDate date] dateByAddingTimeInterval:120];
//keep adding individual dynamic properties
is it correct to set the -toMany relationship sets to nil initially? Or do I need to initialize an (empty?) set here and assign it? Would I be able to add extra objects later if I set the initial set to nil?
newManagedObject.relationshipEvent1 = nil;
newManagedObject.relationshipEvent2 = nil;
//...
// Save the context.
NSError *error = nil;
if (![context save:&error])
{
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
Alex,
You don't need to intialize your relationships. Just use the supplied accessors or helper functions and Core Data takes care of it. IOW, only worry about the property/relationship when you need to actually use it.
Andrew

strange relationship to nsmanagedObject

i have multiple NSmanagedObject from the same entity ( we call PersonEntity).
This entity have a relationship "to-many" for another entity (we call BusinessEntity).
when i populate my store, i create the BusinessEntity managedObject.
After i add this BusinessEntity managedObject to my first PersonEntity managedObject.
[(Person *)entity1 addBusinessObject:businessEntity];
[(Person *)entity2 addBusinessObject:businessEntity];
the addBusinessObject function ( generate by XCode ) :
- (void)addBusinessObject:(NSManagedObject *)value {
NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1];
[self willChangeValueForKey:#"business" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[[self primitiveValueForKey:#"business"] addObject:value];
[self didChangeValueForKey:#"business" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects];
[changedObjects release];
}
this work but only just after the populate.
If i save the store, only the relationShip between the entity1 and the businessEntity exist.
I have no relationShip between entity2 and businessEntity.
Really strange
PS: my two Entity are subclass of NSManagedObject for use with undefined property, and transient property.
Thanks for your help
On the apple documentation Core Data Programming Guide
i have read this important text :
Important: You must define
many-to-many relationships in both
directions—that is, you must specify
two relationships, each being the
inverse of the other. You can’t just
define a to-many relationship in one
direction and try to use it as a
many-to-many. If you do, you will end
up with referential integrity
problems.
Now it's work

Setting up basic relationship with Fetch Requests

I am wanting to set up a basic relationship with two entities in Core Data, but the relationship is either not saving, or is not working properly and I'm not sure why.
The two entities are Character and Avatar, its a one-to-one relationship. A character can have 1 avatar. Technically, it should be a "one avatar can be owned by many characters", but I'll deal with that later.
I want to add characters and assign them an avatar.
There are already 10 avatars in Core Data and 1 character, both of which I've verified via the Terminal and SQLite.
The problem is, I'm having troubling "finding an avatar by a name and then saving the relationship to a character".
So far,
I set up a fetch request called: "frqAvatarWithName" where the Predicate has the following structure:
[quote]
name == $AVATAR_NAME
[/quote]
This is so: I can find an avatar with a certain name; and then I can create a relationship with a character.
Issue 1: It gets to execute the query but then never displays how many records there are.
I get a EXC_BAD_ACCESS error in debug mode and I have traced it back to the fetch request template handling -- so, this must be in error or I have done it wrong.
Issue 2: I am not sure if I am even setting up this "basic" relationship up properly.
[code]
// This code is meant to find an avatar with a certain name and then save the relationship
// between a character and said avatar.
// This is my app delegate file for the moment
// All the files are present, and I have deleted/recreated the app various times
-(void)characterMaker
{
NSLog(#"Inside characterMaker...");
NSError *error = nil;
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObjectModel *model = [self managedObjectModel];
// Find an avatar with a specific name
NSString *nameToFind = #"avt_player_1";
// Use a Fetch request template
NSDictionary *subs = [NSDictionary dictionaryWithObjectsAndKeys:nameToFind, #"AVATAR_NAME", nil];
NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:#"frqAvatarWithName"
substitutionVariables:subs];
// Set the entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Avatar"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Execute the query (it never even reaches this point)
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error
NSLog(#"Error -- %#", [error localizedDescription]);
abort();
}
NSLog(#"Found %# records", [fetchedObjects count]);
// Print out avatar names
for (Avatar *a in fetchedObjects)
{
NSLog(#"Name = %#", [a valueForKey:#"name"]);
}
// This is where I would use `a` and store it in a character entity, and thus create the relationship
[/code]
I gave up on this and did the whole project with the FMDatabase project and SQLite; I've been able to resolve the problem this way.
Thread closed.

Resources