I'm trying to use core data to write a series of persistent data (NSManagedObjects) to sqlite and then read that series in to an application. I have managed to write and read a single record during a single session, but everytime I reload the app the previous data is not loaded (and sqlite manager recognizes tables but does not recognize any entries in the tables).
here is some of the core data logic:
in applicationDidFinishLaunching: i set managedObjectContext property of 3 controllers
inputControl.managedObjectContext = context;
reportControl.managedObjectContext = context;
logControl.managedObjectContext = context;
then in inputControl I add Event NSManagedObjects, such as
[event setDateCreated:[NSDate date]];
and in logControl I read the event logs
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Event" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"dateCreated" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
NSLog(#"Error fetching from DB");
}
int i;
NSLog(#"size of DB: %d",mutableFetchResults.count);
for (i=0; i<mutableFetchResults.count; i++)
NSLog(#"event %d: %#",i,[mutableFetchResults objectAtIndex:i]);
[mutableFetchResults release];
[request release];
When I run this code I see "size of DB:" as always set to '1'. managedObjectModel, managedObjectContext and persistentStoreCoordinator, are being handled in standard way.
Any assistance would be much appreciated
thank you
Peyman
Are you saving your managedObjectContext?
NSError *error = nil;
if (![context save:&error]) {
// Handle the error
}
You can fetch objects you've placed into your context, but unless you save the context to the persistant store, they won't be available next time.
Where are your calls to save? Is it possible you're not flushing to the NSPersistentStoreCoordinator?
I found the problem. The context was not saving (and I was not handling the error) because a mandatory property was not being set before saving (error 1520).
thank you all for your help
Peyman
Related
I want to clear all the data by fetch all records and delete them one by one:
- (void) clear{
for (Program *program in [self getAllProgram]){
[managedObjectContext deleteObject:program];
}
if (![managedObjectContext save:&error])
{
NSLog(#"Problem deleting program: %#", [error localizedDescription]);
}
}
- (NSArray *)getAllProgram{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Program"inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"freq = %#", self.freq];
[request setPredicate:predicate];
// Order the events by creation date, most recent first.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"sid" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
return [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
}
The error is
CoreData: error: Serious application error. Exception was caught
during Core Data change processing. This is usually a bug within an
observer of NSManagedObjectContextObjectsDidChangeNotification.
-[__NSCFSet removeAllObjects]: mutating method sent to immutable object with userInfo (null)
Who can tell me the reason or tell me the one good practice ? thanks!
I suppose you have a fetched results controller somewhere. Set that controller's delegate to nil during the delete. I usually actually set the whole FRC to nil and update my whole data display after a large data change.
If that is not feasible, handle this case in the notification handler, like
if (!userInfo) return;
The static analyzer keeps telling me that I have a +1 retain count for my request object and instruments tells me there is a leak there. However, no matter where I try to release it, it keeps crashing my app. It's the same with NSPredicate object. Please do help, I'm trying to meet a deadline.
// Fetch Requests
// Method that returns an array of NSManagedObjects in the managedObjectContext with a predicate of who ordered
- (NSArray *)fetchDataWithEntity:(NSString *)entity andSortKey:(NSString *)key andPerson:(Person *)whoOrdered
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entity
inManagedObjectContext:managedObjectContext];
request.entity = entityDescription;
// Handling Sorting
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:YES
selector:#selector(compare:)];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// Handling Predicate
if (whoOrdered) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%# == whoOrdered", whoOrdered];
[request setPredicate:predicate];
}
NSError *error = nil;
NSArray *mutableFetchResults = [managedObjectContext executeFetchRequest:request error:&error];
//[request release];
[error release];
if (mutableFetchResults == nil) {
// Handle the error
}
return mutableFetchResults;
}
There is no need to release the error object since you are not the owner of it and you should release the request object just before returning the mutableFetchResults object since you are creating it using alloc and thus are the owner of it ...
I am unsure as to what to use for the YourNameVariable. I think it needs to be an instance of Routine (or maybe the name property of Routine) but how do I create this? I am using a UITableView.
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Exercise" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
[request setPredicate: [NSPredicate predicateWithFormat: #"routineExercises = %#", yourVariableNameHere]];
NSLog(#"After managedObjectContext: %#", managedObjectContext);
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
}
[mutableFetchResults release];
[request release];
Here is my data model:
And also, should I be putting this in viewDidLoad or in the fetchResultsController's method?
You don't need a fetch if you already have the Routine objects. You just ask the Routine object for the contents of its routineExercises relationship.
You use fetches when you don't have an object to start with. If you already have an object, then you walk it's relationships to find it's associated objects. Fetching objects that are already in a relationship defeats the purpose of having relationships in the first place.
Im trying to save a list of Device classes (a custom class) using Core Data and retrieve it. But After I save it, my query, which is VERY simple, doesnt return any records.
My call to save the records always returns YES and no errors:
BOOL resultOfSave = [managedObjectContext save:&err];
My predicate for searching by the property userLogin is like so:
- (NSArray *) devicesForUser:(NSString *)username
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Device" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"userLogin = %#", username];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"macAddress" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error = nil;
NSArray *fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
if (fetchResults == nil) {
// Handle the error.
NSLog(#"ERROR: nil fetch result array");
}
[request release];
NSLog(#"devicesForUser [%#] count %d", username, [fetchResults count]);
return fetchResults;
}
but I always get zero results, if I get rid of the predecate, I get all the objects, and if I loop through them I can see that the userLogin property for at least one of the object IS set to the username that I pass in...
Has anyone ever had an issue like this???
Thanks for any help you can give
Mark
In your predicate, change:
#"userLogin = %#"
...to:
#"userLogin == %#"
NSFetchRequest *req = [NSFetchRequest init];
NSEntityDescription *descr = [NSEntityDescription entityForName:#"City" inManagedObjectContext:context];
[req setEntity:descr];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"streetName" ascending:YES];
[req setSortDescriptors:[NSArray arrayWithObject:sort]];
[sort release];
//fetch
NSError *error;
NSArray *result = [context executeFetchRequest:req error:&error];
//extract names
NSMutableArray *streets = [[NSMutableArray alloc] init];
for () {
??? = [array objectAtIndex:i];
[streets addObject:name];
}
I expected Core Data to be little more intuitive. I am new in it and I could use some help.
I fetched all objects(rows) from the entity (table) City. Now I have an array of objects. From the array I need to extract the attribute “streetName” to an array which will feed the picker. I figured I need to do it in the loop but I could not figure out the way to do it.
Please help.
I have a background with SQL but Core Data is still a big mystery to me. Is there any publication which would take a SQL statement and show comparable Core Data syntax?
Thanks.
It's very simple because of key-value coding:
NSArray *streets = [result valueForKey:#"streetName"];
i think core data changed quite a bit. here is how i do my fetch now
NSError *error;
NSFetchRequest *fr =[NSFetchRequest fetchRequestWithEntityName:#"Category"];
[fr setPredicate:[NSPredicate predicateWithFormat:#"name == \"myCategpry\""]];
NSArray *rs = [self.managedObjectContext executeFetchRequest:fr error:&error];
for (NSManagedObject *index in rs) {
NSLog(#"%#",[index primitiveValueForKey:#"name"]);
}