How to set the relationship between the core data entities? - swift

So, I have a core data database with multiple relationship already populated with data. My problem is that I created the relationships between the tables but i don't know how to set them in code. I only need to set one and then I can figure it out for the rest of them.
For example: Colleges has the "has Groups" relationship because one college has many groups. The Groupe table has the "bellongsToColegiu" relationship becouse one or more groups are in one college.
I know that, i have to set the ".bellongsToCollegiu = Colegiu?" or ".hasGrupe = Grupe?" but i don't know how to fetch the college in proper way.
For now I have only one college in database.
Can someone help me with this please? I've been knocking my head for a few days and got nothing.
Thank you and have a nice day!

When you create entities and relationship between them Xcode also generates code for handling those relationships. The name pattern for code that handles relationships are
The same as the name of the relation for to-one relationships
addToX and removeFromX (x is the relationship) for to-many relationship.
So you should have for instance addToHasGrupe(_ value: Grupe) on College and that you can add a group instance to and Grupe should have a belongsToColegiu property that you can set to a college instance. Autocompletion should help you.

You can fetch a existing 'Colegiu' from the data base or create a new one. for both fetching and creating new one you would need a managed object context. Managed object context is the last part of the data stack which has 3 components comprising of 1. Persistence store, 2. persistence store coordinator, and 3. managed object context.
Here is how to create a stack:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html
Then you can create a new object:
let newItem = NSEntityDescription.insertNewObject(forEntityName: 'Colegiu',
into: 'reference to managed object context here')
or you can search the existing one by calling fetch on managed object context,
Keep in mind CoreData is a complicated topic and it takes time to put the head around. All the best.

Related

How do I update the attributes of an entity with reference to a single attribute of the same entity in CoreData?

My question is similar to a question on this link : Creating a CoreData entity based on attribute evaluation
In have just started coding my first project which uses Core Data, in which I have 5 entities, namely Companies,Meetings,Agendas,SubAgendas and Minutes.
Companies are to be related to Meetings and each Meeting should have a relationship with its 'Agendas' and 'Minutes'... Subsequently each Agendas of a meeting should be related to its 'SubAgendas'
Following represent basic data model of my project:
Companies{
title:string
}
Meetings{
title:string
date:date }
Agendas{
name:string
}
SubAgendas{
name:string
}
Minutes{
name:string
}
I need to code in such a way that if any info about the attributes in any of these entities is changed, it has to be synced.It involves creating new attribute values for each entity or updating the existing attribute values.For this I am planning to have an attribute named ID or tag for each entity, so that once I have set the relationship between each entity, I can update all the other attribute values of an entity with reference to that unique tag value.
Pardon me if my question is confusing.If you can understand, please tell me if what I am planning to do is the right way. I have absolutely no idea about the coding part but I think I can manage if any one can help me with a samples that has been used for similar requirements.
You are going about this the wrong way. Your "tag value" is really nothing but a so-called foreign key in traditional database programming.
But Core Data is not "a database", its an Object Graph. Thus you do not need to use these foreign keys, you just set up relationships between your entities and everything else happens behind the scenes.
Thus, to change an attribute, just do this:
agenda.name = #"New agenda name";
subagenda.agenda.meeting.title = #"New Meeting Title";
So no need to update anything via foreign keys. Welcome to the wonderful world of Core Data.
Please read the Core Data Programming Guide to get a grip on these concepts.

Core data relationships on IOS

I have just redesigned my core data file to make use of relationships and am having trouble getting by head around how i do things with this new model.
I have an entity called data store that had a one-to-one relationship with a second entity called test (test has a many to one relationship with datastore). I am trying to figure out how to store what record in the test entity has been selected. From what i have found from my goggling i should write
[test addDrivingConditionsObject:datastore]
Is this how i should be doing it or is there a way to say
[datastore addTestObject:test] which i would prefer.
Thanks
Assuming that there's a to-many relationship called drivingConditions from test to datastore, then -addDrivingConditionsObject: is the correct accessor name. Accessors need to be named based on the relationship name rather than the type of the object being added because there could easily be several different relationships to the same type of object. Any time this is the case, using the object type would create ambiguity.
First of all, it doesn't really make sense to say that there is a one-to-one relationship from DataStore to Test and a many-to-one the other way.
Most likely DataStore is able to hold references to many Test instances, while Test can only have one reference to a DataStore instance. In this case you have a one-to-many relationship from DataStore to Test and a many-to-one relationship from Test to DataStore. Correct me if I'm wrong.
If I got your modelling correct, DataStore will contain an NSSet property (probably) called tests and Test will contain a DataStore property (probably) called dataStore.
You set the relationship with those properties, and it can be done either way. You can say:
DataStore *dataStore = // get instance of DataStore
Test *test = // get instance of Test
// Possibility one - add Test to DataStore
[dataStore addTestsObject:test];
// Possibility two - add DataStore to Test
[test setDataStore:dataStore];
// ... or you can use dot notation
test.dataStore = dataStore;

Where can I find a good example of a Core Data to-many relationship?

Does anyone have a tutorial or source code that shows a to-many relationship being used, where the user add elements in on the fly? I would just like to have a look because reading about it hasnt been much help.
People are often confused by to-many relationships because one entity represents the relationship as a set while the other represents it as a single object. Take the following entities:
EntityA{
name:string
bees<-->>EntityB.a
}
EntityB{
name:string
a<<-->EntityA.bees
}
In EntityA, the relationship bees is a set because there maybe many EntityB objects in the relationship. So, using Key-Value coding, you would have to access the relationship using a mutableSetForKey: expanding everything out to see the detail would like so:
NSMutableSet *muteSet=[anEntityAObj mutableSetValueForKey:#"bees"];
[muteSet addObject:aNewBObj];
[anEntityAObj setValueForKey:#"bees"];
...or more compactly:
[[anEntityAObj mutableSetValueForKey:#"bees"] addObject:aNewBObj];
If you set from the EntityB side, however, you are only adding a single object so you can just use setValueForKey: directly like so:
[anEntityBObj setValueForKey:anEntityAObj];
That's if you use generic NSManagedObject instances to represent your entities. If you create custom subclasses then you have properties and methods to do the setting for you:
[anEntityAObj addBeesObject:anEntityBObj];
anEntityBObj.a=anEntityAObj;
Remember as well that with managed objects, setting one side of a relationship defined as reciprocal automatically set the other side as well and removing works the same way.
Update
Lets say i've got 2 entities --
Person:with "name" attribute --
Times:with "time" attribute -- i would
want to set multiple times for each
name, but how to I tell it which name
i would like to add the specific times
to?
You don't create relationships with attributes, in this case name but rather with an object, in this case an instances of the Person entity/class. Each individual Person object is completely separate from all other Person objects even if they have the same value in their name attribute.
You must obtain a reference to any particular Parent object. If you have just inserted a new Parent object then you already have a reference to it. If it is already been inserted/persisted, then you create a fetch with a predicate that will return the proper object. Once you have the correct Parent object you then just add the Time objects to the relationship.
So, if your entity looks like this pseudo-code:
Parent{
name:string
times<-->>Time.parent
}
Time{
theTime:date
parent<<-->Parent.times
}
... and you are using generic NSManagedObjects to instatiate you entities, you set the relationship between an existing Parent object and new Time object something like this:
NSManagedObject *existingParent= //... results of a fetch
NSManagedObject *newTime=[NSEntityDescription insertNewObjectForEntityForName:#"Time" inManagedObjectContext:self.moc];
[newTime setValue:[NSDate date] forKey:#"theTime"];
[newTime setValue:existingParent forKey:#"parent"];
Note that if you set the relationship from the Time object's side, you can use setValue:ForKey: because from the Time object's perspective the relationship is just one object to one object.
It is really quite simple once you start thinking in objects instead of databases. Each object you insert in a context is unique even if it shares attributes with other objects of the same entity/class. That is why you can set a relationship between specific objects without necessarily worrying about the values stored in their attributes.
Here is an example of a one-to-many relationship, as long as you have set up the relationships so they have an inverse they are quite easy to manage. at the end, Entity1's chilren attribute will contain entity2 and entity3
Entity1 *entity1=[NSEntityDescription insertNewObjectForEntityForName:#"Entity1" inManagedObjectContext:self.managedObjectContext];
Entity2 *entity2=[NSEntityDescription insertNewObjectForEntityForName:#"Entity2" inManagedObjectContext:self.managedObjectContext];
Entity2 *entity3=[NSEntityDescription insertNewObjectForEntityForName:#"Entity2" inManagedObjectContext:self.managedObjectContext];
[entity2 setParentEntity:entity1];
[entity3 setParentEntity:entity1];
NSError *error;
[[self managedObjectContext]save:&error];
NSSet *set=[entity1 children];
Get Marcus Zarra's book "Core Data" (you can buy a PDF rather than paper for instant gratification...) It too presents examples in Mac OS X but it goes a lot further than just getting started. You will find out useful things like versioning, transition rules, optimization. This book saved one of my projects from being late & slow!
I am currently using this ebook and its very well written:
It explains and shows how to create datamodels and there are also there are code examples..
"Pro Core Data for iOS"
http://apress.com/book/view/1430233559
Hope it helps
Download the iPhoneCoreDataRecipes sample code. It's a full working demo of Core Data and an excellent way to get familiarized with the concepts.
You could try to see in the "Learn Cocoa on the Mac" book sources. In the chapters 7 and 8.
Here for the book
Here for the sources
I hope you'll find what you need
See Apple's Core Data Programming Guide.
I create objects and add them to relationships using mutableSetValueForKey:
mutableSetValueForKey: returns a mutable proxy object. If you mutate its contents, it will emit the appropriate key-value observing (KVO) change notifications for the relationship.
Ray Wenderlich has great Core Data tutorials.
this one deals with to-many relationships
which builds off
this great 3-part intro to core data tutorial

How to create Entity dynamically in Objective-C?

I'm building an iPad application where I need user to create entity dynamically. I'm already having 3 entities which program uses.
Could you help me with code how to do it?
I want to understand the whole structure according to my understanding I have to create new managedObjectModel, add new entities and than merge it with existing one, is it correct?
While it is possible to create a new entity and a new model on the fly in practice this is massively complex. If nothing else you would have to migrate any existing persisted data to the new model and a new persistent store file. I strongly recommend against attempting this especially if you are just starting out with Core Data.
You do have options:
Firstly, are you sure you actually need a new entity? People just starting out with Core Data often mistake entities for managed objects. Entities are to managed objects as classes are to instances. Entities are abstractions used to create the object graph. They don't actually contain data. The times when you need new entities are very,very rare.
Secondly, if you do need some kind of dynamic entity, it would usually be best to decompose the dynamic entity into numerous fixed subentities and then use relationships to create a virtual entity. E.g. you need a dynamic Person "entity" so you create several entities in the model each of which holds one attribute of the person. You could have a Field entity which would have a fieldName attribute and then a fieldValue attribute. Then have a an actual Person entity that has no attributes but just relationships to the necessary Field objects. You could add any fields needed to any person and then reconstitute an virtual person object by walking the relationships to its fields.
I rather doubt however that you need that kind of flexibility. Such a need is very rare. I would step back and see exactly what dynamic data you think the user might need to enter.
That's correct -- you'd create an array of NSEntityDescription objects, then call setEntities: on the new managed object model. Then, finally, you'd merge that model with your built-in model.
But note that you can't change a model once it has been used to create a managed object context (or used for storage). You'll need to create new storage and context after the model is changed.

iphone Core data and entity inheritance

This is a two part question, here is the situation:
I have an app that lists a set of product models. The user should be able to select from this list the product models that they specifically own. They can own more than 1 of the same type of product and should also be able to set a custom name for the products they own. So I set up my data model with two entities. Product, and OwnedProduct. OwnedProduct inherits from the Product entity and adds a customName property.
Question 1: Is this the best way to implement the model or should I be doing something with relationships? Right now I don't have any relationships in place.
The next question involves actually creating an OwnedProduct record from one of the Products that has been selected by the user.
Question 2: Is there a way to take the selected Product object, duplicate it , and then cast it as an OwnedProduct? Or would I have to create a brand new instance of OwnedProduct and then manually assign all of it's properties from the properties of the Product instance?
Question 1: Is this the best way to implement the model or should I be doing something with relationships? Right now I don't have any relationships in place.
Do you plan to have multiple owners within the same context?
Can a single product be owned by different owners with different custom names?
If yes I would take a look at relationships. I would not duplicate a product because of an ownership. If the product changes, it probably should change for all owners.
A possible datamodel for your requirements:
Question 2: Is there a way to take the selected Product object, duplicate it , and then cast it as an OwnedProduct? Or would I have to create a brand new instance of OwnedProduct and then manually assign all of it's properties from the properties of the Product instance?
As the clone will be a separate instance within your context you have to create a new one and copy all necessary properties. You can speed things up by iterating over NSEntityDescription properties and relationships. There is already a solution to cloning NSManagedObjects on SO