I've the following problem:
I have two or more persistent stores. And I have created an entity in the xcdatamodel named "House". Now I have these two files for the NSManagedObject House.
Now I want to know how do I save an instance of the entity house in a specific persistent store?
So I tried to work with [NSEntityDescription insertNewObjectForName:#"House" inManagedObjectContext:context] and [context assignObject: toPersistentStore:]. But it didn't worked until now. Am I on the right way to do it?
Can somebody give me a hint?
Answering my own question:
The problem was that I allocated a completely new persistentStoreCoordinate who coordinates all the stores. So the coordinator wasn't linked to the managedObjectContext.
Could be solved with
__persistentStoreCoordinator = [__managedObjectContext persistentStoreCoordinator];
Related
What method will be called by Core Data on NSManagedObject when setting a value for to-one relationship? What method will be called when adding a value to to-many relationship? Thanks.
/Mikael
Maybe you are looking for something like:
Managed Object Accessor Methods - Core Data Programming Guide
Its like this
managedObjectInstance.property = value;
[self.managedObjectContext save:&error];
Ex: if you want to save username in user entity it will be
_userEntity.username = #"Mikeal Hakman";
[self.managedObjectContext save:&error];
One to Many or Many to May always carries NSSet example
_residenceEntity.Seller = [NSSet setWithObjects:seller, nil];
[self.managedObjectContext save:&error];
Obviously I didn't manage to formulate my question clearly enough. I'll try again.
In a subclass of NSManagedObject I need to know when to-many and to-one relationships are being changed. That includes the very first change when the object is being fetched or inserted. I try all the accessors described in https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coredata/articles/cdAccessorMethods.html to no avail. I can see in my UI that the relationship is there but no accessor methods has been called on my object. Also when I remove the relationship, it goes away in UI but no methods on my object are called. Thanks.
/Mikael
What I have is a Core Data Entity called "MyDocument" which has these properties
fileName
fileExtension
fileURL
I download a bunch of files from the server, save them on the disk in the "Caches" Folder and then Insert rows in the DB for each document. This just makes it easier to manage documents in the app without listing directory contents etc...
Everything seems OK, except that when I delete the Entity, I also want to delete the associated file on disk. I could easily do something like this
for(MyDocument *myDocument in ParentEntity.mydocuments)
{
[[NSFileManager defaultManager] removeItemAtURL:[NSURL fileURLWithPath:myDocument.fileURL] error:nil];
[context deleteObject:myDocument];
}
But I am trying to get this done via accessors....so that I can call - deleteObject:myDocument from anywhere and be sure that the associated file would also get deleted.
I know I could use Core Data's External File Storage option and not worry about this at all but I am using QLPreviewController to preview these documents, and QLPreviewController needs a file URL to be able to preview the item. And if I save the documents in Core Data, I would have to write the file to disk from the stored NSData every time Preview needs it. It did not make sense so I decided to store them externally myself and keep a reference in DB.
So, how would I write a custom accessor that would jump in just before object is about to be deleted and delete the associated file and then carry on with deleting the actual Entity..
Thanks in advance
NSManagedObject -prepareForDeletion is most certainly what you need to implement in your entity, to take care of associated resources.
Core Data calls prepareForDeletion for every deleted entity while still alive and well and before the delete rules propagation. This is the right place to implement anything more complex than the very basic rules Core Data provides.
It works without adding stuff to the NSManagedObjectContext, it will work with the default NSManagedObjectContext -deleteObject, and it will not mess with the NSUndoManager. Of course, you have to use custom classes for your entities.
I think the cleanest way is to simply add a custom method to your NSManagedObject subclass. Below I made this a category of NSManagedObjectContext, but you could also do it just as a MyDocument instance method. In this way you can explicitly delete the Entity and associated document while still having the option to just delete the entity. Also, you would avoid deleting things accidentally in the future when you not that familiar with your code any more ;-).
#interface NSManagedObjectContext (customDelete)
-(void)deleteMyDocumentObjectAndAssociatedFiles:(MyDocument *)object;
#end
#implementation NSManagedObjectContext (customDelete)
-(void)deleteMyDocumentObjectAndAssociatedFiles:(MyDocument *)object {
[[NSFileManager defaultManager] removeItemAtURL:
[NSURL fileURLWithPath:object.fileURL] error:nil];
[self deleteObject:object];
}
#end
Or as MyDocument method (don't know if this "self deletion" works):
-(void)deleteSelfAndAssociatedFiles {
[[NSFileManager defaultManager] removeItemAtURL:
[NSURL fileURLWithPath:self.fileURL] error:nil];
[self.managedObjectContext deleteObject:self];
}
I'm new to Cocoa and xCode, but not programming though.
I have created some some core data and a interface in the interface builder.
Now i need to edit and get some core data from my code. In fact I need to be able to get an "imagepath" to show a picture and to set a new value in the "imagepath".
"imapepath" is a core data attribute.
I have figured out how to insert a new entry, but i want to edit values instead.
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *places = [NSEntityDescription
insertNewObjectForEntityForName:#"Place"
inManagedObjectContext:context];
[places setValue:[tvarNSOpenPanelObj filename] forKey:#"imagepath"];
I hope you guys have some clues ;-)
If you have loaded your NSManagedObject from CoreData, then you can edit it's values just like any other object. This is stored in your NSManagedObjectContext (ie. just in memory).
You then need to persist this to your backing store at some point, so you need to call save: on your NSManagedObjectContext - and voila, it's saved.
You should read the programming guide for core data:
http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/coredata/cdProgrammingGuide.html#//apple_ref/doc/uid/TP30001200-SW1
(If you don't know how to load an object from Core Data, read the section on 'Fetching Managed Objects', and then 'Using Managed Objects' to know how to edit them).... in fact, read it all from the beginning to the end. Its invaluable for knowing how to use CoreData correctly and effectively.
I've got a few questions I've been trying to answer for myself (by hunting through the documentation) but I have a feeling I'm missing something.
Any hints (and/or pointers to appropriate documentation) would be much appreciated.
I'm building a Core Data document-based application. There are essentially two entities:
There is a single "Comparison" record associated with each document.
There are potentially many "Node" records associated with each document.
My first question is whether I'm thinking about this correctly. Since there is only a single Comparison object for each document, the attributes of the Comparison are essentially attributes of the Document itself. What (if any) is the preferred way of modeling that?
If a Comparison entity is in fact the right way to go, my next question is how and when to actually instantiate the (single) Comparison object. The user should not have to explicitly "add" the Comparison since there's going to be only one of them associated with the Document. Instead, a single Comparison object should be instantiated and inserted into the managedObjectContext. I've got something like this working already, with code in MyDocument.m that looks like this:
(void)windowControllerDidLoadNib:(NSWindowController *)windowController {
[super windowControllerDidLoadNib:windowController];
[NSEntityDescription insertNewObjectForEntityForName:#"Comparison" inManagedObjectContext:managedObjectContext];
}
However -- if the user creates a new document but then never does any work with it -- for example if he immediately clicks the close button -- then he should not be asked to "Save" the document. He should be asked to save his work only if he's actually entered any information. Is there a preferred way to implement this behavior?
I found this thread while struggling with the exact same issue. I have a table of Entity_A working in my document based Core Data app, but I need to figure out how to handle a required single-instance per document of Entity_B.
I've found something that seems to work. There's probably a better way, but this is getting me past this hurdle for now.
When the document's xib is loaded I simply check to see if an Entity_B has been created. if not, I create one and initialize its attributes.
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
//has an Entity_B been created? if not, create one.
NSError *theError = nil;
NSUInteger count = [[self managedObjectContext] countForFetchRequest:[NSFetchRequest fetchRequestWithEntityName:#"Entity_B"] error:&theError];
if( count == 0 )
{
NSManagedObject *newEntity_B = [NSEntityDescription insertNewObjectForEntityForName:#"Entity_B" inManagedObjectContext:[self managedObjectContext]];
[newEntity_B setValue:[NSNumber numberWithBool:YES] forKey:#"boolAttribute"];
[newEntity_B setValue:[NSNumber numberWithInt:2] forKey:#"intAttribute"];
}
}
I didn't insert that code snippet into the original post correctly. Trying again:
-(void)windowControllerDidLoadNib:(NSWindowController *)windowController {
[super windowControllerDidLoadNib:windowController];
[NSEntityDescription insertNewObjectForEntityForName:#"Comparison" inManagedObjectContext:managedObjectContext];
}
Your question about modelling is not very clear, can you please elaborate on what your "Comparison" entity is supposed to do and what sort of attributes you are assigning to it? It would be handy to see your "Document" entity structure so we can provide some useful input.
With regards to your second question, you could check if your NSManagedObject has been updated before deciding on whether to prompt the user to save their document or not:
if ([documentObject isUpdated]) {
...
}
More details in the documentation here http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObject_Class/Reference/NSManagedObject.html#//apple_ref/occ/cl/NSManagedObject
Cheers,
Rog
There isn't really a "Document" entity, I was simply using that term to refer to the overall document that is saved when the user invokes the Save menu item. Perhaps there is a better way to refer to this concept? NSPersistentDocument?
Backing up a bit... the central idea of the application is to compare two hierarchical directory structures (a visual recursive "diff").
For now the "Comparison" entity has two string attributes, pathA and pathB, which are the names of the two directories to be compared. Each "Node" entity represents the name of a file down in the directory trees that are being compared. The Node entity contains at least one attribute ("relativePath") which is the path relative to the starting point specified in the Comparison.
My first question was simply whether it makes sense for there to be a "Comparison" entity since there is going to be only one of them instantiated (at some point after the user invokes the "New" menu item).
The second question is really at what point should the single "Comparison" object be instantiated and inserted into the managedObjectContext, i.e. what method is most appropriate to make this happen?
Finally if a "Comparison" object is automatically instantiated (at awakeFromNib time, perhaps?) but the user decides not to proceed, and simply clicks the close button, he should not be prompted to save (right?) What would be the appropriate way to accomplish this? The documentObject will appear to have been updated, because an "empty" Comparison object has in fact already been inserted automatically at startup, but the user has not modified it.
Hope that's clear... thanks.
Dear all.
Currently i need to extract necessary objects from core data but i have just attribute name in entity. TO setup reverse relationship, i find just one way to loop around all objects in managed objects, compare strings for checking necessary attributes accordance and setup relationship. May someone have better way. relationship carrier is part of NamesTranslationRules Entity and connect to Carriers Entity
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:#"Carriers"
inManagedObjectContext:moc]];
NSArray *carriers = [moc executeFetchRequest:request
error:&error] ;
for (NSManagedObject *carrier in carriers)
{
if ([[carrier valueForKey:#"name"] isEqualToString:[tempRules valueForKey:#"carrier"]]) [namesTranslationRules setValue:carrier forKey:#"carrier"];
}
A parent object's is create at application startup as carrier's name with some attributes. Later user have to choice a name from another source and based on user's choice we have to add appropriate entity, which have already present parent entity carrier.
What do you mean by a reverse relationship? If the relationship is already bi-directional then the reverse will be set up for you automatically by Core Data.
If you mean something else, you can look at using a predicate on your NSFetchRequest to pre-filter the objects and skip the string comparison.
Update 1
You should know the parent object at the time of the creation and should be connecting them at that time.
Where is the data coming from?