I have a UILabel that displays a managed object of EntityA. I want use the text of that UILabel as a definition for an EntityB managed object. My first question is, is this possible? I'm trying to pull the text and establish it's properties as those of EntityB here:
NSString *temp = managedObjEntityA.nameA;
managedObjEntityA.name = self.UILabel.text;
self.UILabel.text = temp;
EntityB *textEntityB;
temp = textEntityB.nameB;
My hope is to use the defined textEntityB as reference for a newly created object to establish relationship with:
createdObject.objectToB = textEntityB;
Every version I've tried I get nul for textEntityB. How would I call the managed object of EntityB that matches that of EntityA?
You first have to insert EntityB into your managed object context.
EntityB *newB = [NSEntityDescription insertNewObjectForEntityForName:#"EntityB"
inManagedObjectContext:context];
newB.name = aObject.name;
// or
newB.name = self.label.text;
// establish the (to-one) relationship
aObject.objectToB = newB;
Related
I need to create an instance of a NSManagedObject that will not be saved in CoreData and only in memory.
e.g.:
I have the Item and Log NSManagedObject, and they have relations between them.
I want to be able to create a Log instance without any core data properties, and assign its item property to an Item instance.
I know I can create it in a different, memory-persistence, context (or nil context). But then I can't assign the item property, since my Item instance is in the core-data context.
NSEntityDescription *description = [NSEntityDescription entityForName:#"Log" inManagedObjectContext:defaultContext];
Log *log = [[Log alloc] initWithEntity:description insertIntoManagedObjectContext:nil];
log.item = item;
This code throws an exception when ran:
Illegal attempt to establish a relationship 'item' between objects in different contexts
How can I achieve this in another way?
You can create a NSManagedObjectContext with parent context set to your Log's MOC.
Do you need the relationship to have an inverse? If not, you could use the ObjectID for the item objects as an attribute in the Log entity. You would need to convert the ObjectID to its URIRepresentation, and then convert that to a NSString:
NSURL *itemURI = [item.objectID URIRepresentation];
NSString *itemURIstring = [itemURI absoluteString];
log.itemURI = itemURIstring;
(If item has not yet been saved to the database, it will have a temporary ID - you should test for this with item.objectID.isTemporary otherwise the objectID may change). When you want to find the Item object for a given Log object, reverse the process:
NSURL *itemURI = [NSURL URLwithString:log.itemURI];
NSManagedObjectID *itemObjectID = [self.context.persistentStoreCoordinator managedObjectIDForURIRepresentation:itemURI];
Item *item = [self.context objectWithID:itemObjectID];
Pretty cumbersome!
I guess if you need an inverse, you could do the same (i.e. store a URI for the Log object as a string in Item).
I have a CoreData entity , (myEntity) which has assume 10 properties. Is there a way to get the 10 properties in an array and set the property values using said array?
For example:
//To get the property:
NSArray *arrayOfProperties = <Some command>;
...
//and then to set the property value,instead of:
myEntity.property1 = <value>;
//set the property like so:
[[arrayOfProperties objectAtIndex:1] <some command to set the value>];
Something like the following:
// Create the entity in the managed object context:
MyEntity *myEntity = (MyEntity *)[NSEntityDescription insertNewObjectForEntityForName:#"MyEntity" inManagedObjectContext:[self managedObjectContext]];
// Set the properties of the entity:
entity.property1 = arrayOfProperties[0];
entity.property2 = arrayOfProperties[1];
entity.property3 = arrayOfProperties[2];
// etc...
I have the following simple relationship:
Parent has many Children (ordered)
Child belongs to Parent.
And I get a strange behaviour:
// In of my classes, I keep a reference to a child.
#interface Foo ()
{
Child *_child;
}
// Somewhere in my code I create a child and a parent and associate them.
Child *c = (Child *)[NSEntityDescription insertNewObjectForEntityForName:#"Child" inManagedObjectContext:moc];
Parent *p = (Parent *)[NSEntityDescription insertNewObjectForEntityForName:#"Parent" inManagedObjectContext:moc];
[p addChildrenObject:c];
c.parent = p;
_child = c;
// Then somewhere else I do:
Parent *parent = _child.parent; // It works fine
NSOrderedSet *children = parent.children; // Same, I do see the children
int idx = [children indexOfObject:_child]; // idx is NSNotFound!!
What I can see is children contains childs with normal IDs, whereas my _child reference still has a temporary ID.
I am using the same context everywhere.
I guess I am doing something wrong with my references, but I am not sure what it is?
In response to your last comment:
I believe it happens when the child ID is updated from temporary to
permanent. Somehow Core Data does something that breaks the reference.
You are almost certainly correct. Here is an exert from the documentation about objectId:
Important: If the receiver has not yet been saved, the object ID is a
temporary value that will change when the object is saved.
That being said, if you have some other unique property on the child you could do use KVO to run comparisons:
int idx = [[children valueForKey:#"uniqueProperty"] indexOfObject:_child.uniqueProperty];
I have a base class #interface BaseMailbox : NSManagedObject and I have two children of it.
It seems like it's possible to create an object of my class only the next way:
BaseMailbox *mailbox;
mailbox = [NSEntityDescription
insertNewObjectForEntityForName:#"BaseMailbox"
inManagedObjectContext:context];
So it seems like Core Data objects don't support polymorphism?
EDIT:
Before to create my mailbox object for example I used:
account = [[GoogleMailbox alloc]
initWithFullName
and when I called account.connect - it was a connection with gmail params.
But now account doesnt refer to any of the children object and when I call account.connect- it calles base class method.
EDIT2
BEFORE CORE DATA:
if([_emailAddress.text endsWith:SUFFIX_GOOGLE]){
account = [[GoogleMailbox alloc]
initWithFullName:_fullName.text emailAddress:_emailAddress.text password:_password.text];
}else if([_emailAddress.text endsWith:SUFFIX_YAHOO]){
account = [[YahooMailbox alloc]
initWithFullName:_fullName.text emailAddress:_emailAddress.text password:_password.text];
}else{
..........
BOOL success = [account connect]; // GoogleMailbox or YahooMailbox or ...,depending the account refers to.
CORE DATA:
BaseMailbox* account = [NSEntityDescription
insertNewObjectForEntityForName:#"MailBox"
inManagedObjectContext:context];
}else{
..........
BOOL success = [account connect]; // BaseMailbox
Core Data entities support an inheritance concept.
An entity "A" can be defined as "Parent Entity" of another entity "B" in the
Data Model Inspector. This is reflected in the corresponding managed object subclasses:
B is a subclass of A.
So you could define an entity "BaseMailbox" and make that the parent entity of
"GoogleMailbox" and "YahooMailbox". Attributes which are common to all subclasses are
defined in the parent entity.
Then
[NSEntityDescription insertNewObjectForEntityForName:#"GoogleMailbox"
inManagedObjectContext:context]
returns an GoogleMailbox object, which is a subclass of BaseMailBox.
To improve the readability of my code, I have been generating Core Data classes for my entities so I can access them using getters and setters (I personally use the dot notation) rather than setValue: forKey:
For example, instead of [aDateObject setValue:nameString forKey:#"name"];
I will use: aDateObject.name = nameString;
I was wondering if there is an equivalent approach for inserting a new managed object into the managed object context. For example, I currently create a new DateTimeFlightDataType with the following:
aDateObject = (DateTimeFlightDataType*)[NSEntityDescription insertNewObjectForEntityForName:#"DateTimeFlightDataType"
inManagedObjectContext:self.managedObjectContext];
Is there a way to create and insert this object into the context using my class (DateTimeFlightDataType) rather than the entity string name for consistency?
You can write:
NSString *name = NSStringFromClass([DateTimeFlightDataType class]);
NSManagedObjectContext *ctx = self.managedObjectContext;
aDateObject = [NSEntityDescription insertNewObjectForEntityForName:name
inManagedObjectContext:ctx];
creating a MO always requires an entity and these are always defined by a string.
the common approach is to somehow make it so the string doesn't need to be hardcoded but can be derived from the MO's class.. typically using NSStringFromClass