I am trying to save some data to my core data table. I am experiencing a trouble that only one column value is not saved with the value passed.
I have almost wasted a day to figure this out.
[contactObj setLastName:#"Hey"]; NSLog(#"LAST NAME CHECk : %# %#",
[contactDict objectForKey:#"LastName"], contactObj.lastName); // Here contactObj.lastName
its printing.But not saved
Please suggest /help.
Did you call the "save" method of your NSManagedObjectContext instance? It has a cache mechanism and may cause your problem. Try this:
NSError *err = nil;
[INSTANCE_NAME_OF_YOUR_NSManagedObjectContext save:&err];
Related
I have an NSManagedObject (User) in database. Then I'm trying to fetch that object from database and update field firstName:
NSFetchRequest *fetchR = [NSFetchRequest fetchRequestWithEntityName:#"User"];
NSError *err = nil;
NSArray *allUsers = [self.managedObjectContext executeFetchRequest:fetchR error:&err];
TMUser *profile = allUsers.firstObject;
[profile setValue:#"Username" forKey:#"firstName"];
[self.managedObjectContext save:&err];
if (err) {
NSLog(#"Error: %#", err.localizedDescription);
}
The code passes without errors. But if I relaunch my app, fetch request retunrs user without updated field "firstName". I have only 1 NSManagedObjectContext. All Core Data stack was initialized successfully. After fetch my user is:
Printing description of allUsers:
<_PFArray 0x14ed6600>(
ID:3451
firstName:Johnatan
lastName:Hike
phone:380995046960
email:igor#email.com
language:en
)
For some reason object changes wasn't registered in context(Context hasChanges = NO before save). What am I doing wrong? Please, help
I think you are not saving the master context.
Please check that you call:
[managedObjectContext save:&error];
on all child contexts that save the data,
and after that on the master context as well.
You have one global function(in AppDelegate) saveContext which saves everything and which I can call from anywhere safely.
I solved my problem. I recreated NSManagedObject subclass from xcdatamodeld scheme and it works. I found that if I add another properties(readonly etc.), not related to data model scheme or change property type from NSNumber(aka bool) to BOOL, it stops updating existed objects in database.
I have a relatively simple entity. When I create it, set its attributes, and save it, it saves successfully. I can later retrieve it and it is not nil and I get a successful save message from MagicalRecord.
When I retrieve it and try to access any attribute though the attribute is nil. The entity itself is fine but the attributes are all nil. I have checked they are all definitely set correctly before I save.
I haven't encountered this problem before. Why could it be occurring?
NB: This doesn't happen every time. Most times I call the method to create and save this entity it can later be retrieved without any issues. The problem is intermittent but possible to replicate on every run.
Code:
Entity1 *entity1 = [Entity1 MR_createEntityInContext:localContext];
[entity1 setUpEntity:myobject];
EntityChild *entityChild=[EntityChild MR_createEntityInContext:localContext];
[entityChild setUpEntityChild:entity.child withContext:localContext];
[entityChild setEntity1:entity1];
[localContext MR_saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
}];
Update:
If I look in the sqlite database and search for the entity it actually doesn't exist at all. So MagicalRecord tells me it saves, CoreData lets me retrieve a non-nil object (albeit with nil attributes) but no record exists in the database.
I did not understand ur code standards. As I am new to IOS Development. I Used below code for retrieving.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityRef = [NSEntityDescription entityForName:#"Entity1" inManagedObjectContext:appDelegate.managedObjectContext];//localContext
[fetchRequest setEntity:entityRef];
NSError *error=nil;
NSArray *detailsArray = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(#"Unable to execute fetch request.");
NSLog(#"%#, %#", error, error.localizedDescription);
}
Saving the data
NSManagedObjectContext *context = [appDelegate managedObjectContext];//localContext
NSManagedObject *objectRef = [NSEntityDescription
insertNewObjectForEntityForName:#"Entity1" inManagedObjectContext:context];
[objectRef setValue:#"IOS" forKey:#"Name"];
[objectRef setValue:#"positive" forKey:#"Attitude"];
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
Hope it helps you...!
Ok, I got to the bottom of this. It wasn't a problem with the code when I did the save. It was actually a problem with some code in another class that was retrieving the data from the wrong context. When I changed the context it worked correctly.
I'm still not sure why this only happened occasionally and not every time the code was run but it's working now.
Thanks for your help anyway everyone.
In my application I have trip, which has many stops. This has been specified in the .xcdatamodeld file. I can go ahead an manipulate trips in any manner that I want and they all work okay. However, I am running into issues with adding many stops to each trip. It does not seem to persist. Here is the following code. this code is inside of a a detailViewController of a trip, so a specific trip has already been clicked on.
Trip * trip = [self retrieveObjectWithID:_passedObjectId];
StopOff *newStop = [NSEntityDescription insertNewObjectForEntityForName:#"StopOff" inManagedObjectContext:managedObjectContext];
[newStop setValue:stopName forKey:#"stopName"];
[newStop setValue:stopCity forKey:#"stopCity"];
[newStop setValue:stopDate forKey:#"stopDate"];
[newStop setValue:stopAddress forKey:#"stopAddress"];
[newStop setValue:stopState forKey:#"stopState"];
[newStop setValue:stopTime forKey:#"stopTime"];
newStop.trip = trip;
[trip addStopObject:newStop];
NSLog(#" stop count %i", [trip.stop count]);
Here is what my console spits out the first time i hit a button to run this: CoreData: annotation: to-many relationship fault "stop" for objectID 0x8bb2810 <x-coredata://4CE70783-4729-46E0-B18B-8E325D1020CC/Trip/p20> fulfilled from database. Got 0 rows 2013-11-24 21:19:43.417 Tracker[30633:70b] stop count 1
If I keep hitting the button, stop count increases. If I relaunch the app the stop count goes back down and starts over again, so it seems that it is not persisting.
My question is, how exactly do I insert many stops that correspond to a trip, and once they are inserted and persist, how do I go ahead and get every corresponding stop to that trip.
Here is the code for which retrieves each trip just fine. and managedObjectContext is handled in the parent view controller using NSFetchedResultsController. Please let me know if you need anymore information
- (Trip*)retrieveObjectWithID:(NSManagedObjectID*)theID
{
NSError *error = nil;
Trip *theObject = (Trip*)[self.managedObjectContext existingObjectWithID:theID error:&error];
if (error)
NSLog (#"Error retrieving object with ID %#: %#", theID, error);
return theObject;
}
You are not saving your context after applying the changes (new StopOff objects).
After adding a StopOff, call [managedObjectContext save:&error] and you will persist your new object to the store.
CoreData does not save automatically, and without a save: being called, you will loose any temporal changes made to the context.
also, there is no need for [trip addStopObject:newStop]; as CoreData is taking care of that as part of the inverse relationship.
You have a to-many relationship setup: you don't need both newStop.trip = trip and [trip addStopObject:newStop]. I think this is why you are getting your warning.
At some point, you will want to call:
NSError *error = nil;
[managedObjectContext save:&error];
I am trying my hand at some very basic implementation of MagicalRecord to get the hang of it and run into the following.
When I save an entry and then fetch entries of that type it will come up with the entry I just saved. However, when I save the entry, close the app, start it again, and then fetch, it comes up empty.
Code for saving:
- (void)createTestTask{
NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread];
Task *task = [Task createInContext:localContext];
task.tName = #"First Task";
task.tDescription = #"First Task created with MagicalRecord. Huzzah!";
NSError *error;
[localContext save:&error];
if (error != Nil) {
NSLog(#"%#", error.description);
}
}
Code for fetching: (all I want to know here if anything is actually saved)
- (void) fetchTasks{
NSArray *tasks = [Task findAll];
NSLog(#"Found %d tasks", [tasks count]);
}
I am sure I am missing something here, but not anything I can seem to find on stackoverflow or in the Tutorials I looked at.
Any help is welcome.
I have to ask the obvious "Is it plugged in" question: Did you initialize the Core Data Stack with one of the +[MagicalRecord setupCoreDataStack] methods?
Did your stack initialize properly? That is, is your store and model compatible? When they aren't, MagicalRecord (more appropriately, Core Data) will set up the whole stack without the Persistent Store. This is annoying because it looks like everything is fine until it cannot save to the store...because there is no store. MagicalRecord has a +[MagicalRecord currentStack] method that you can use to examine the current state of the stack. Try that in the debugger after you've set up your stack.
Assuming you did that, the other thing to check is the error log. If you use
[localContext MR_saveToPersistentStoreAndWait];
Any errors should be logged to the console. Generally when you don't see data on a subsequent run of your app, it's because data was not saved when you thought you called save. And the save, in turn, does not happen because your data did not validate correctly. A common example is if you have a required property, and it's still nil at the time you call save. "Normal" core data does not log these problems at all, so you might think it worked, when, in fact, the save operation failed. MagicalRecord, on the other hand, will capture all those errors and log them to the console at least telling you what's going on with your data.
When i have started with magical record I was also facing this problem, problem is context which you are using to save data. here is my code which might help you
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
NSArray *userInfoArray = [UserBasicInfo findByAttribute:#"userId" withValue:[NSNumber numberWithInt:loggedInUserId] inContext:localContext];
UserBasicInfo* userInfo;
if ([userInfoArray count]) {
userInfo = [userInfoArray objectAtIndex:0];
} else {
userInfo = [UserBasicInfo createInContext:localContext];
}
userInfo.activeUser = [NSNumber numberWithBool:YES];
userInfo.firstName = self.graphUser[#"first_name"];
userInfo.lastName = self.graphUser[#"last_name"];
userInfo.userId = #([jsonObject[#"UserId"] intValue]);
userInfo.networkUserId = #([jsonObject[#"NetworkUserId"] longLongValue]);
userInfo.userPoint = #([jsonObject[#"PointsEarned"] floatValue]);
userInfo.imageUrl = jsonObject[#"Picturelist"][0][#"PictureUrL"];
userInfo.imageUrlArray = [NSKeyedArchiver archivedDataWithRootObject:jsonObject[#"Picturelist"]];
} completion:^(BOOL success, NSError *error) {
}];
Use this when your done
[[NSManagedObjectContext MR_defaultContext]saveToPersistentStoreAndWait];
I'm getting a "failed to save" error, no. 1620, when I try the following:
NSManagedObjectContext *context = [self managedObjectContext];
CustomObject *objToInsert = [NSEntityDescription insertNewObjectForEntityForName:#"CustomObject" inManagedObjectContext:context];
objToInsert.variable1 = [NSNumber numberWithFloat:10.0];
objToInsert.variable2 = [NSDate date];
objToInsert.variable3 = [NSNumber numberWithInt:1];
NSError *error;
if (![context save:&error]) {
NSLog(#"failed to save with error = %#", [error localizedDescription]);
}
This same logic works just fine when saving other NSManagedObject-subclass objects to the managedObjectContext. The 1620 error is listed as being a "number too small" validation error, but there's clearly nothing wrong with the numbers I'm inputting. The three variables are defined in my data model as Float, Date and Integer 16, though I'm not sure whether that's
relevant.
The Core Data stack is all present and correct and as I said, works just fine with other insertion logic. Am I missing something here?
EDIT: turns out from the error output that Core Data is trying to save a completely different NSManagedObject subclass, which I work with earlier in execution but not in this method call. Why would this be?
In the end, the solution was partly as suggested by Martin R (see comments) but for a completely different entity. It appears that if a required minimum value is set for any other entity in the data model, and that entity is modified and saved at some prior point, any subsequent saves to other entities will cause an error. This does not seem to be sensible - maybe I'm doing something wrong elsewhere? - but removing the minimum value requirement did solve this particular problem.