How to get parent object from relation in Parse - ios

Let's say I have a class Parent that has a one-to-many relation with a target class Child. Both Parent and Child objects are not user created, I am creating this objects in Data Browser and I don't know how to set a relationship or a pointer on a Child back to it's particular Parent. I can get Child objects of a Parent with no problem. But, how can I get the Parent of a Child? I don't want to keep passing both Parent and Child objects from VC to VC. Once again both objects are NOT user created so I can't do:
[Parent setObject:Child forKey:"child"];
and then query Parent class like this:
[query whereKey:#"child" isEqualTo:Child];
Also querying all Parents and their relations and then getting that particular Child and then going back to the Parent seem to be an overkill.
So, how can I set the particular Parent on a Child object in Data Browser to point back to the parent? And how to get that Parent object from the code if I want to use only Child object?

This is a case of where using a reverse pointer might be more useful. This can be done in addition to your existing relationship if you want, but requires some fancier save logic.
Simply add a parent column to Child that is of type Pointer<Parent>.
To get all children of a parent you just do a query:
[childQuery whereKey:#"parent" isEqualTo:parent];
To query a child and also get the parent:
[childQuery includeKey:#"parent"];
// filter as needed
In the block that looks are children you can just use:
PFObject *parent = child[#"parent"];
It will be a fully populated Parent due to the includeKey:.
NOTE: if you keep both relationships, creating new objects gets trickier as you'll have to save the parent/child (with child.parent unset) then update the child to point to the parent and save it again.

Related

Parent Child Context Confusion & Concurrency issues

Am having few doubts with parent child context set-up and how the data behaves. Can anyone please suggest a link where i can find proper explanation on how they work.
Few Points & Observation
Parent context acts as store for child context :- But the changes in the parent are not reflected in the child.
Question 1: If parent context acts as store for child context then why does the changes in the parent are not reflected in the child context, while the child fetches them.
Observations :
Insert in parent :- Child fetch requests get those objects.
Update/delete a object in parent :- Then the fetch request do not get the updated object instead it provides us with the object in child context, so if we need the updated object we have to either reset the context but then we will lose all the changes in the child context or refresh the object.
Question 2: Child overwrites parent context values. So if the user has modified something in parent context and child has also modified the same thing then the updates of user will be lost. This is not much problem until relationships are involved.
Say there is one to many relationship between entity A,B (A->>B).
Parent Context : Inserts a new child to entity A say Child-1.
Child Context : Deletes both entity A and all its child.
So now when the child saves to parent context, then it deletes entity A and its old child, the newly inserted child-1 remains in the context with null referencing parent.
How can i resolve this issue?
Question 1
Because you have already fetched the data, if you want to force a fetch as you said you should either reset the context or refresh the object.
Question 2
You can try to use cascade delete if you want to always delete entities B when the parent entity A is deleted.

Core data Parent Child Context Implementation Confusion

Am using a parent-child context syncing data with cloud kit. Am facing a problem of child overwriting the parent data. I know this is how it works but is there anything that can be done.
Below is the exact scenario.
Model
Parent Entity : A
Child Entity : B
A->>B is one to many relationship.
Context:
Parent Context (MOC) :- Used for CRUD operation by users.
Child MOC (CMOC) :- Used for syncing data from cloud kit.
Senario:
A parent is deleted from child context
A child for that parent is inserted on parent context.
If the save of child occurs, it overwrite the parent moc while leaving the newly inserted child without a parent.
So this leaves a child which don't have any reference parent.
When parent is deleted from child context, it will also be deleted from the parent context when save is performed. Changes from child contexts are propagated to parent context. This is by design.
What are you trying to accomplish? There may be another way.

How to automatically delete any entity when all its relationships are nil?

I have a simple Core Data app that has a many to many relationship from entity A to B. I have kept the delete rule as nullify.
I simply want that when all entities of type A that relate to an entity of type B are deleted. In other words, when all relationships from a given B to A are nil, that particularly object of entity B should be deleted.
Now I noticed that, at least for me, this isn't happening automatically. Do I have to manually check to see if a given B object has all relationship to A as nil and then delete them manually or is there an automatic way to achieve it?
In your NSManagedObject subclass
- (void)willSave
{
// Check for relationship and delete self if empty
}
...or is there an automatic way to have this happen?
Yes if you let Core Data to manage this.
If you have two entites, say Parent and Child where the former has a one-to-many relationships with the latter
you can set the children relationship with a Delete Rule Cascade.
On the contrary, the parent relationship would be
The check on the optional flag depends on if a Child could exist with or without a Parent associated with it.
Here the delete rules mean the following.
If I delete a parent, all the children will be deleted. If I delete a child, nothing would happen on the parent (in other words the parent won't be deleted).
The inverse relatioship between the Child and the Parent is very important since lets Core Data to maintain the graph consistency. So, you should (a must for me) use it in every model you have.
Is this what you want to achieve? Let me know if you need something else.
Update 1
Only children can be deleted and not the parent. And I want that when
all children of a given parent are deleted, the parent object should
be removed from the store as well. the parent cannot be directly
deleted.
Deleting a parent it's up to you. In your code you will just not delete a parent if you want. I would use the configuration I provided since, if you delete a child, the parent will remove the reference to it.
To delete all the children that belong to a specific parent I would use a simple fetch request against Child where the predicate would be
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"parent == %#", parentOfTheChildrenYouWantToDelete];
Once run, the request will return a NSArray of managed objects. for in to delete them.
In my understanding of your question, I recommend you look into running a specific fetch at a certain point in your code to check for nil against the relationship, and then delete manually.
So to answer your question, my understanding is that there is no "automatic" mechanism.

Reject Changes Does Not Remove Entity From Parent

When I create a new entity and set its navigation property and then reject the changes the parent holds onto a blank entity. Do I need to explicitly remove the new entity from the parent before rejecting changes? I did not explicitly add it to the parent I just set the new entity's parent id.
Rejecting changes on a new entity simply discards the entity - making its entityState 'detached'. Any children that were attached to the parent effectively get stranded in this case, i.e. they have no parent.
In other words, Breeze does NOT call rejectChanges on any children as a result of a rejectChanges on a parent. This is deliberate.
So your best bet is to call rejectChanges on the children as well. If they were new entities themselves they will also become detached, otherwise their parents will revert to whichever entity was their previous parent.
Note that you can use the EntityManager.getEntities method to return all of the entities of specified entityTypes and entityStates. This can be useful in determining which entities you want to 'roll back'.
See the Entity Manager getEntities method

Core Data: child object nothing inheriting parent's relationships

I have a parent entity of class SomeObject that has three relationships:
Parent
Children
SomeRelationShipWithAnotherObjectOfADifferentClass
The Parent relationship is a many-to-one and the Children is a one-to-many. They both point to objects of the same class (SomeObject).
When I spawn a child I add the relationship to his parent, that works as-expected; but I also expected the other relationship (SomeRelationShipWithAnotherObjectOfADifferentClass) to be inherited but it fails.
Any tips?
Thank You
Edit #1
Here is my NSManagedObjectModel; I'm trying to make the children [of entity SomeEntity] inherit [some of] their parent's relationships.
I think you are confusing parent and children relationships, which define a tree structure basically, with (object oriented) inheritance.
If you are interested in parent's relationships, you can always access them through the Parent relationship:
self.Parent.SomeRelationShipWithAnotherObjectOfADifferentClass
if you defined custom classes, or:
[obj valueForKeyPath: #"Parent.SomeRelationShipWithAnotherObjectOfADifferentClass"]
if not.

Resources