narner
narner

Reputation: 3221

Core Data saving to Only One Entity

I'm a bit confused about saving entities using Core Data. I'm making a screen that will allow users to save their settings (contact information), which can be changed later if they wish.

From what I understand, my code below will save multiple entities each time the 'save' button is pressed.

- (IBAction)saveSettings:(id)sender {

    AppDelegate *appDelegate =
    [[UIApplication sharedApplication] delegate];

    NSManagedObjectContext *context =
    [appDelegate managedObjectContext];
    NSManagedObject *userSettings;


    userSettings = [NSEntityDescription
                  insertNewObjectForEntityForName:@"UserSettings"
                  inManagedObjectContext:context];
    [userSettings setValue: _firstName.text forKey:@"firstName"];
    [userSettings setValue: _lastName.text forKey:@"lastName"];
    [userSettings setValue: _userEmail.text forKey:@"userEmail"];
    [userSettings setValue: _zipCode.text forKey:@"zipCode"];
}

What I don't understand how to do is save one entity, and then change the values of the attributes later on whenever the user types in new values in the appropriate text fields and presses 'save'.

Upvotes: 0

Views: 1549

Answers (2)

pbasdf
pbasdf

Reputation: 21536

Yes - because you use insertNewObjectForEntityForName:, a new UserSettings object is created each time that method is run. What you probably want to do is to fetch the existing settings from the database, update your textFields with that data, present the view and let the user amend the details as necessary, and then (when they press the save button), save that data back to the database.

I would add userSettings as a property:

    @property (strong, nonatomic) NSManagedObject *userSettings;

and in your method delete the declaration of userSettings, and the line where you use insertNewObjectForEntityForName.

Then create a new method to handle fetching the data from the database and assigning it to your textFields, as follows:

-(void)loadSettings {

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext *context = [appDelegate managedObjectContext];

    NSFetchRequest *fetch = [NSFetchRequest fetchRequestWithEntityName:@"UserSettings"];
    NSError *error;
    NSArray *results = [context executeFetchRequest:fetch error:&error];
    if (results == nil) {
        // some error handler here
    }
    if ([results count] > 0) {
        userSettings = [results lastObject];
        _firstName.text = [userSettings valueForKey:@"firstName"];
        _lastName.text  = [userSettings valueForKey:@"lastName"];
        _userEmail.text = [userSettings valueForKey:@"userEmail"];
        _zipCode.text = [userSettings valueForKey:@"zipCode"];
    } else {
        // set your text fields to some defaults values??
    }
}

Call this method when your view controller loads, in the viewDidLoad method. I've assumed that you will normally have only one UserSettings object (hence lastObject will be the only object!). If you could have many UserSettings objects, you would need to filter the fetch to get only the one you want. To do that you would need to set a predicate for the fetch - look at the documentation for NSPredicate.

Upvotes: 1

Marcos Curvello
Marcos Curvello

Reputation: 917

You are actually overwriting those properties everytime you "set". The correct way to store individual properties is to assign them and save, like so:

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSManagedObject *userSettings;


userSettings = [NSEntityDescription insertNewObjectForEntityForName:@"UserSettings"
              inManagedObjectContext:context];


userSettings.firstName = _firstName.text;
userSettings.lastName  = _lastName.text;
userSettings.userEmail = _userEmail.text;
userSettings.zipCode   = _zipCode.text;


NSError *error = nil;
if (![context save:&error]) {

    NSLog(@"Error Saving: %@", error);
}

Upvotes: 0

Related Questions