CoreData: Accessing Objects through Relationships - core-data

Three entities in CoreData:
User
EntityA
EntityB
Relationships:
EntityA has one-to-many Relationship with User & inverse
EntityA has one-to-one Relationship with EntityB & inverse
User & EntityB have no relationships
Objects created:
UserA creates an objectA of Type EntityA listing UserB and UserC as the relationship objects.
UserA also creates ObjectB of type EntityB, listing ObjectA, as its relationship Object
Accessing Objects
UserB logs in and fetches in EntityA and successfully downloads ObjectA.
Question: Will UserB be able access ObjectB? If so, can UserB access ObjectB with the following code: NSString *value = [ObjectA.OneToOneRelationshipBetweenEntityAandB valueForkey"#attributeFromObjectB"];
If not, how can UserB access ObjectB? What relationships do I need to establish?
I had asked a similar question earlier but I thought I gave too much information and made it confusing. I deleted that question and hopefully simplified it down to this one.
Thanks.

Assuming a unified core data model, you can easily access objects as long as there are relationships.
For the purpose of readability, I am redefining your variable / relationship names:
User <<-----> Group <<-----> Community
Community has many groups has many users. This is simple enough and looks like a viable setup.
To clarify: a user cannot create an object. Only a program can do that.
Group *newGroup = [NSEntityDescription
insertNewinsertNewObjectForEntityForName:#Group"
inManagedObjectContext:self.managedObjectContext];
Community *newCommunity = [NSEntityDescription
insertNewinsertNewObjectForEntityForName:#Community"
inManagedObjectContext:self.managedObjectContext];
userA.group = newGroup;
userB.group = newGroup;
newGroup.community = newCommunity;
Now both userA and userB belong to newGroup and the group is one of the groups in newCommunity. userB is linked to the group, so it is really easy to access the community:
Community *aCommunity = userB.group.community;

Related

Giving your own ids to Core Data objects

I have some points on a map with associated informations contained by Core Data, to link the points on the map with the associated info, I would like to have an ID for each point, so in my entity, I would need some ID property, I have read that Core Data has it's own IDs for every managed object but I'm wondering wether or not it would be a good approach for me to directly use them or if I should create my own ID system ?
If you think I should create my OWN ID system, how would I do that ?
Thank you.
CoreData is not an relational database and you should avoid thinking about own ID’s. You may need them only for syncing purposes with external databases. For more precise answer, you should write how your model looks.
[edited after comment]
I don't see that you need any relations. Let's sat you have MapPoint entity with lat, and long properties. If there is only one user note, you just add another property to it like notes. If you have many informations (many records) stored with one MapPoint you need to add Notes entity with properties note and mappoint and make a relation between them. When you insert new Notes object into CoreData you set mappoint property to already existing MapPoint object (fetched after user tap).

How to fetch data from relationship in Core Data in iOS 8?

I have two entities Employee and Department. Both are related with Relationship i.e., 1-to-M and M-to-1. Dept is having attribute called MANAGERID representing the employee Id who is the manager of that dept.
Now i need to fetch DeptName and the Manager Name. How to write the Predicate Format String ?
NOTE: I am working in iOS 8.3 with Xcode 6.3 and Swift 1.2
Thanks in Advance.
If you follow the usual setup described in Apple's documentation, there is no need for ids. To access the department of an employee
let department = employee.department
To get all employees of a department
let employees = department.employees // returns NSSet or [Employee]
Following the design pattern of object graphs, rather than holding a manager id in the Department object, you should just have a one-to-one relationship with the manager.
let manager = department.manager // returns an Employee
This means that you need a separate relationship for the manager:
Department.employees <----->> Employee.department
Department.manager <------> Employee.managedDepartment
Also note that an all-caps attribute name like MANGAERID is illegal in Core Data.

Getting NSEntityDescription relationships

I have a core data model like so:
SALES_REP <--->> CUSTOMER <---->> PURCHASE_AGREEMENT <<------->> PRODUCTS
I can get the entity description for the Purchase Agreement and I can get the relationships (toCustomer and hasProducts)
[NSEntityDescription relationshipsByName];
but is it possible to get the Sales_Rep as well or do I have to pull that through the CUSTOMER entity?
Thanks
According to your diagram, SALES_REP isn't directly related to PURCHASE_AGREEMENT, it's only linked via CUSTOMER. That means SALES_REP doesn't know anything about PURCHASE_AGREEMENT on its own. So yes, you'll have to move on to the entity description for CUSTOMER and ask it for its relationshipsByName. I'm not sure what you're trying to do here, but it would be easy to recursively look up relationships on an entity, then its related entities, and their related entities, etc, until you don't find any new ones.

Multiple similar entities or use the same one in core data?

So I've got a Client entity that needs a relationship to a PhoneNumber entity to allow multiple phone numbers. And I've got an Employee entity that also needs a relationship to a PhoneNumber entity to allow multiple phone numbers. Should I create two separate PhoneNumber entities or can I somehow use the same entity for both?
I would create a parent entity called Person for your Client and Employee entities. The Person entity would have a relationship to the PhoneNumber entity.
Inherited entities have the same attributes and relationships as their parent entity. Of course you can add attributes and relationships to the "child"-entities as well. I omitted that in the screenshot.
Something like this:
you can configure the parent entity in the core data inspector in the right side pane.

Core Data: Can relationship be used for sectionNameKeyPath?

I am trying to do exactly same thing as post in NSFetchResultsController + sectionNameKeyPath + section order, i.e. basically use 2 tables, let's say Categories <-->> Events. Category table consists of category field only, while Event consists of name, dateTimestamp.
I defined relationship 'category' in Events table and try to use that relationship as sectionNameKeyPath when creating fetchedResultsController:
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"category.category" cacheName:#"Root"];
Finally, I pre-populated Category table with some categories upon loading of the app (and verified with .dump that table is populated correctly)
Yet, I simulator fails on:
return [[self.fetchedResultsController sections] count];
I did extensive search and most people either suggest using one of the fields in the table as sectionNameKeyPath (this works!) or transient property (works too!) However, I just want to use relationship as it seems very logical to me in this case where events belong to some categories and there could be categories without events. Am I wrong in my assumption that relationship can be used as sectionNameKeyPath? The original link at the top of the question suggests it works, but guy does not know why or how. Documentation is very weak on what can be used as sectionNameKeyPath, so any help will be highly appreciated.
A relationship gets you a pointer to a managed object. It seems logical, though, that the sectionNameKeyPath parameter should be a key path that leads to a string, since NSFetchedResultsSectionInfo's name property is a string. The fetched results controller will follow that key path for each fetched object and group the objects into sections based on what they return for that key path, and it'll also use those strings as the names of their respective sections. You can't use a managed object for the name -- you have to use some string property of the managed object.
So, your Category entity must have an attribute that distinguishes one category from another, right? Use that as the key path and (as you've seen) everything will work out.
BTW, I think it's useful to try to get out of the database (rows/fields) mindset and try to think in object-oriented terms like entity and attribute. A big selling point of Core Data is that it provides an abstraction layer that hides the storage mechanism. Thinking in terms of tables is like thinking about blocks and sectors when you're reading or writing a file.
Caleb, thank you for your answer. I do believe my understanding was wrong to some degree. What I had was an entity Category and entity Event. Category has a string field 'category', thus 'category.category' path (first 'category' is relationship in the Event entity)
What I did not take in account, though, is that if there are no events, fetchresultscontroller cannot fetch anything (similar to 'left join')
What I wanted is to show categories even if there are no events. Relationship 'category' will not return anything in this case as there is nothing to return/sort/categorize.
What I had to do (wrong or right - not sure yet) is to treat [managed] object created from Category entity as a separate object in case there are no events and place in the table. When there is one event per category, I can switch to the original method of [automatic] showing events sorted by categories.
This is interesting issue of starting point (empty entities with relationships) where I feel core data is more confusing than traditional relationship database. I also believe that's why all books/articles/reports carefully stay away from this topic. In other words, I could not find analog of "left join" in core data. May be I am wrong because I am relatively new to all this. Below is the description of the entities:
Category <-->> Event
Category - parent
Category.category - attribute of type String
Category.event - relationship to Event entity
Event - child
Event.name - attribute of type String
Event.category - relationship to Category entity
Each event belongs to one category. Category may have multiple events.
Categories should be shown even if there are no events for this category.
I was trying to put Events under fetchresultscontroller. May be I should switch to Category first and then calculate cell based on category.event relationship, not the other way around - did not try that yet.

Resources