CoreData saving object is not successful - ios

I am trying to update int data by using CoreData but I think I am missing some parts before updating the object. Here what I am trying to do to save the int value. Here I want to both save and update only first object value.
- (IBAction)btnYakClicked:(UIButton *)sender
{
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Kalorimetre" inManagedObjectContext:context]];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
NSManagedObject* kaloriObject = [results objectAtIndex:0];
NSNumber *valWeek = [NSNumber numberWithInteger:300];
NSNumber *valMonth = [NSNumber numberWithInteger:1000];
[kaloriObject setValue:valWeek forKey:#"thisweek"];
[kaloriObject setValue:valWeek forKey:#"thismonth"];
}

I don't see the line where you're saving it. For example:
NSError *saveError;
if (![context save:&saveError]) {
NSLog(#"Error: %# %#", saveError, [saveError localizedDescription]);
}
It might also be a good idea to limit the fetch request since you're only looking for the first object:
[request setFetchLimit:1];
I would hope that this would improve performance but cannot confirm.

Related

Update NSManagedObjectContext

Please consider the method at the end of this question. It attempts to delete all records from a CoreData entity.
The first -outcommented- part works fine: it deletes everything from my context, and then saves the context.
The second, non-commented part doesn't seem to work:
As a test I do
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"myEntity"];
NSError *error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];
NSLog(#"Fetch request returns %lu objects", (unsigned long)[results count]);
When I add records, and delete all records with the method below, the amount of records only increase.
As far as I understand, it actually works, but the context is not aware of it (yet).
So, therefore, in order to get a reliable context, I should update the context with
[NSManagedObjectContext mergeChangesFromRemoteContextSave:<#(nonnull NSDictionary *)#> intoContexts:self.managedObjectContext];
However, I don't have a clue what I should enter in the (nonnull NSDictionary *) part.
BTW: I only want to use the NSBatchDeleteRequest because I assume it is faster than iterating through all records.
- (void)deleteAllEntities:(NSString *)nameEntity
{
id appDelegate = (id)[[UIApplication sharedApplication] delegate];
self.managedObjectContext= [appDelegate managedObjectContext];
/*
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:nameEntity];
[fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSError *error;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *object in fetchedObjects)
{
[self.managedObjectContext deleteObject:object];
}
error = nil;
[self.managedObjectContext save:&error];
*/
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:nameEntity];
NSBatchDeleteRequest *delete = [[NSBatchDeleteRequest alloc] initWithFetchRequest:request];
NSError *deleteError = nil;
}

How to update coredata value in Objective-C

I am new in iOS and I am facing a problem regarding to update value of coredata.
For Save
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *device;
if (self.device) {
// Update existing device
[device setValue:GlobalIndexPath forKey:#"key"];
} else {
// Create a new device
NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:#"Device" inManagedObjectContext:context];
[newDevice setValue:GlobalIndexPath forKey:#"key"];
}
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
My code to fetch core data is
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"EntityName" inManagedObjectContext:context]];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
And to update I and using code
NSManagedObject* favoritsGrabbed = [results objectAtIndex:0];
[favoritsGrabbed setValue:#"1" forKey:#"Key"];
Update code not update it add one object.
Note - GlobalIndexPath is a name of string.
But this is not working for me any suggestion. Thanks in Advcance!
You need to save the context every time you make changes to any NSManagedObject and want it to persist. Try this:
NSManagedObject* favoritsGrabbed = [results objectAtIndex:0];
[favoritsGrabbed setValue:#"1" forKey:#"Key"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}

Why coredata is returning null array while I am inserting values in table

I have two methods,
In first method, I do save values in Core Data, while in other, I simply fetch them.
After inserting, when I fetch data in same method, it shows value, but when I try to fetch in other method if returns me null.
My saving Method is
-(void) saveloginData:(NSString *)facebookTok username:(NSString *)userName password:(NSString*)password flag:(NSString *)flag {
NSError *error;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"SignIn" inManagedObjectContext:context]];
[fetchRequest setIncludesPropertyValues:NO]; //only fetch the managedObjectID
NSString *facebookTokenData = facebookTok;
NSString *usernameData = userName;
NSString *passwordData = password;
NSString *flagData = flag;
NSLog(#"Facebook Token%#\nUsername%#\npassword%#\nflat%#\n",facebookTokenData,usernameData,passwordData,flagData);
SignIn *signIn = [NSEntityDescription
insertNewObjectForEntityForName:#"SignIn"
inManagedObjectContext:context];
signIn.facebookToken = facebookTokenData;
signIn.username = usernameData;
signIn.password = passwordData;
signIn.flag = flagData;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SignIn"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedArray = [context executeFetchRequest:fetchRequest error:&error];
for (SignIn *info in fetchedArray) {
\\ THis executes and shows values, proves that value are inserted.
NSLog(#"Name ~~~~ : %#", info.username);
NSLog(#"Password ~~~~~~~~ :%#", info.password);
NSLog(#"FLAG ~~~~~~~~~~~ %#",info.flag);
NSLog(#"Facebook Token %#", info.facebookToken);
}
}
My retrieve Method is
-(NSArray*) getLoginData {
NSError *error;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"SignIn"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSArray *fetchedData = [[NSArray alloc] init];
fetchedData = [context executeFetchRequest:fetchRequest error:&error];
NSLog(#"The count of Array %d", [fetchedData count]); \\ HERE COUNT IS ZERO, WHY?
for (SignIn *info in fetchedData) {
NSLog(#" FF Name ~~~~ : %#", info.username);
NSLog(#"Password ~~~~~~~~ :%#", info.password);
NSLog(#"FLAG ~~~~~~~~~~~ %#",info.flag);
NSLog(#"Facebook Token %#", info.facebookToken);
}
return fetchedData;
}
Please guide that where I am doing mistake.
Your problem is that you need to save conext to get the entity it later.
NSManagedObjectContext save: Attempts to commit unsaved changes to registered objects to their persistent store.
- (BOOL)save:(NSError **)error
Parameters: error: A pointer to an NSError object. You do not need to create an NSError object. The save operation aborts after the first failure if you pass NULL.
Return Value YES if the save succeeds, otherwise NO.
So you need to save context after you modify your object:
signIn.facebookToken = facebookTokenData;
signIn.username = usernameData;
signIn.password = passwordData;
signIn.flag = flagData;
[context save:NULL]; // NULL if you don't need to handle error

iOS - update managed object if matching found

I just cant seem to figure out how to update core data object after I fetch the object that I want to modify.
This is what I'm trying to do :
1) Find 1st object from core data matching predicate conditions :
NSInteger storeId = 235; //find object with this id in core data
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:[self.managedObjectContext persistentStoreCoordinator]];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Store"
inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"id == %i",storeId];
[request setPredicate:predicate];
NSArray *results = [context executeFetchRequest:request error:NULL];
2) If match found, update matching object (This is where I need help) :
if (results != nil && [results count] > 0)
{
/** Not sure how to get the correct context and modify object **/
Store *matchingObject = [results objectAtIndex:0];
[context setValue:[NSNumber numberWithInteger:storeId] forKey:"id"];
}
/** Save the context */
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
//abort();
}
Thank you for any help you can provide...
Try modifying the object property directly and saving it:
matchingObject.id = [NSNumber numberWithInteger:storeId];
The object was originally fetched with context so you should be able to save your changes by calling save on context.

Pro Core Data book, example code question

I'm learning Core Data with the help of the book. There is a code:
- (void)loadData {
// Pull the movies. If we have 200, assume our db is set up.
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Movie"
inManagedObjectContext:context]];
NSArray *results = [context executeFetchRequest:request error:nil];
if ([results count] != 200) {
// Add 200 actors, movies, and studios
for (int i = 1; i <= 200; i++) {
[self insertObjectForName:#"Actor" withName:
[NSString stringWithFormat: #"Actor %d", i]];
[self insertObjectForName:#"Movie" withName:
[NSString stringWithFormat: #"Movie %d", i]];
[self insertObjectForName:#"Studio" withName:
[NSString stringWithFormat: #"Studio %d", i]];
}
// Relate all the actors and all the studios to all the movies
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Movie"
inManagedObjectContext:context]];
NSArray *results = [context executeFetchRequest:request error:nil];
for (NSManagedObject *movie in results) {
[request setEntity:[NSEntityDescription entityForName:#"Actor"
inManagedObjectContext:context]];
NSArray *actors = [context executeFetchRequest:request error:nil];
NSMutableSet *set = [movie mutableSetValueForKey:#"actors"];
[set addObjectsFromArray:actors];
[request setEntity:[NSEntityDescription entityForName:#"Studio"
inManagedObjectContext:context]];
NSArray *studios = [context executeFetchRequest:request error:nil];
set = [movie mutableSetValueForKey:#"studios"];
[set addObjectsFromArray:studios];
}
}
[request release];
NSError *error = nil;
if (![context save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
The main question is: is it necessary to renew the context pointer, if there were any changes in that context?
What I mean: I get the pointer to the context at the beginning of the method, next in the loop I take this context and insert managed objects there (-insertObjectForName:withName:). Then I see this renewal of the context pointer and have that question: is it a rule of some kind, and I should act the same, or its just not-so-neat code example? Why can't I use the old pointer?
---Edit--- One more question: is that a legal initialization of a request here in the code:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
...
NSFetchRequest *request = [[NSFetchRequest alloc] init];
...
[request release];
Two allocs and only one release?
I also have this book and looked it up.
Clearly seems like a typo to me and doesn't really make much sense.
Just ignore that line and continue - it should work fine without.
In my opinion
its just not-so-neat code example
About your second question: There have to also two releases! Otherwise you have a leak.
That's some seriously ugly code.
This:
NSManagedObjectContext *context = [self managedObjectContext];
... is probably just because they want to be able to write context in a method call instead of self.managedObjectContext.
Using:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
... twice is allowed but it is lazy bad practice. Any variable should be named only once in a scope. In fact, the compiler will generate a warning with this code. It will leak because every init must be balanced by a release.

Resources