Reputation: 5536
I have check the following Q&A and while the solutions are much the same the issue remains for me remains: Saving an updated Core Data instance
Update/Edit coreData managed object
How to update existing object in Core Data?
I have a log in/log out feature in my app.
The Core Data entity "NewLog" has the following attributes
String loginTime
String logoutTime
String loginStatus
String name
When I login it creates a new object in the core data. When I log out I have the object update.The issue is when I logout it updates the existing object but creates a new object also.
Here is my "save" code from my super class so that I don't have to continuously rewrite it and risk errors in my classes:
- (void) saveAndDismiss{
NSError * error = nil;
if ([self.managedObjectContext hasChanges]){
if (![self.managedObjectContext save: &error]){
NSLog(@"Save Failed: %@", [error localizedDescription]);
}
else {
NSLog(@"Save Successful");
}
}
[self dismissViewControllerAnimated:YES completion:nil];
}
In my loginViewController implementation file to update the "loginStatus" and "logoutTime":
- (IBAction)logOutButton:(id)sender {
//access the managed object context and create a shortcut name
NSManagedObjectContext *context = [self managedObjectContext];
//refer to the entity in the core data
NSEntityDescription *entity = [NSEntityDescription entityForName: @"NewLog" inManagedObjectContext:context];
//create a request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity: entity];
// Results should be in descending order of loginTime.
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"loginTime" ascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
//create an array of results
NSArray *results = [context executeFetchRequest:request error:NULL];
NewLog *latestEntity = [results objectAtIndex:0];
//refer to the specific value that I wish to change
NSString * statusOfLogin = latestEntity.loginStatus;
//if the loginStatus in my app is currently YES
if ([statusOfLogin isEqual:@"YES"]){
//create a date formatter
NSDateFormatter *dateformatter=[[NSDateFormatter alloc]init];
//format as such
[dateformatter setDateFormat:@"dd MMM yyyy , HH:mm:ss"];
//convert to a string
NSString *dateInStringFormated=[dateformatter stringFromDate:[NSDate date]];
//hide logout button and display login button
_logOutButton.alpha = 0.0;
_loginButtonStatus.alpha = 1.0;
//status declared as String in .h file
status = @"NO";
//update the object found in "latestEntity"
latestEntity.logoutTime = dateInStringFormated;
//set the login status to be NO
latestEntity.loginStatus = status;
//BOOL declared in the .h file
logStatus = false;
self.loginLabel.text = @"Logged Out";
self.dateLabel.text = dateInStringFormated;
[super saveAndDismiss];
}
}
When I save the updated data it creates a new object containing only the logoutTime and loginStatus.
Is there a solution to stop the new object being created?
Thanks
EDIT
I know that it is creating a new object the following ways: 1. The SQL file displays the new object with the content stated above - logoutTime and loginStatus 2. The tableview displays the new object and in the detail view for it displays the two items.
Checking the area it's coming from is my segue:
//prepare for segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
//first check whether the segue is equal to our transition name
if([[segue identifier]isEqualToString:@"loginSegue"])
{
//tell the segue where to go
UINavigationController *navigationController = segue.destinationViewController;
//create reference to view controller
LoginViewController *loginVC= (LoginViewController*) navigationController.topViewController;
//create the new object
NewLog *addLogDetails = [NSEntityDescription insertNewObjectForEntityForName:@"NewLog" inManagedObjectContext: [self managedObjectContext]];
loginVC.logEntry = addLogDetails;
}
}
I know why it's creating a new object but how do I prevent this from happening while remaining able to save?
Upvotes: 0
Views: 792
Reputation: 119242
Nothing in the code in your question is creating a new managed object, so either the problem is elsewhere in your code or you're mistaken that an extra object is being created - you don't say how you have come to this conclusion.
To identify the problem, implement awakeFromInsert
on your NewLog
object and add a breakpoint. This will be hit every time one of these objects is added, you can then examine the stack trace to find out where the object is being added from.
UPDATE
OK, having done that, you see that you're making a new entity every time the segue is performed. Don't do that. You need to perform a fetch to find the existing login object, and only if there isn't one, or the existing one isn't suitable, create a new one.
If you do a fetch and there's nothing in the array, objectAtIndex:0
will crash. Use firstObject
instead and check if the result of that is nil.
Upvotes: 1