App Dev Guy
App Dev Guy

Reputation: 5536

Updating object value in core data is also creating a new object

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

Answers (1)

jrturton
jrturton

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

Related Questions