1

I am struggling with the editing/saving in Core Data and need some help in this. I am using NSFetchedResultsController and have an entity named Golfer with attributes- first_name, last_name, email_id and others in Core Data. So, I know how to add and remove golfers from the database.

I am working on one view controller called ViewManager (kinda base view for all my classes) and it has 2-3 Custom UIViews inside it. I animate them in and out whenever I need them.

I add a golfer to the tableview, then on didSelectRow tableview method, I present my edit View inside the same ViewManager controller and try to update the textfields in the edit view using the following code, but it's updating at random indexes in the tableview and not working for me. Any help would be greatly appreciated.

- (IBAction)saveEditGolfersView:(id)sender
{
    AppDelegate * applicationDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
    NSManagedObjectContext * context = [applicationDelegate managedObjectContext];

    // Retrieve the entity from the local store -- much like a table in a database
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Golfer" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity]; 

    // Set the sorting -- mandatory, even if you're fetching a single record/object
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"first_name" ascending:YES];

    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1,nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release]; sortDescriptors = nil;
    [sortDescriptor1 release]; sortDescriptor1 = nil;

    NSError * error;

    NSArray * objects = [context executeFetchRequest:request error:&error];

    for(int i = 0; i<[objects count]; i++)
    {
        Golfer * golfguy = [objects objectAtIndex:i];

        golfguy.first_name = mEditFirstName.text;
        golfguy.middle_name = mEditMiddleName.text;
        golfguy.last_name = mEditLastName.text;
        golfguy.email_id = mEditEmailField.text;
        golfguy.contactNumber = mEditContactNum.text;
        golfguy.picture = mEditPictureView.image;

        NSLog(@"name-%@", golfguy.first_name);
    }

    [request release]; request = nil;

     error = nil;
    [context save:&error];

    [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseOut

                     animations:^ {

                         mEditGolfersView.frame = CGRectMake(-480, mEditGolfersView.frame.origin.y, mEditGolfersView.frame.size.width, mEditGolfersView.frame.size.height);

                     }

                     completion:^(BOOL finished) {
                         mEditGolfersView.hidden = YES;

                     }];
}
Nikita Pestrov
  • 5,876
  • 4
  • 31
  • 66
Angad Manchanda
  • 183
  • 5
  • 17

1 Answers1

1

If I have read this code correct, then a call to -(IBAction)saveEditGolfersView:(id)sender will set all the Golfers with the exact properties, which I expect is not what you want.

I am not quite sure what the problem is, but I hypothesize that you need an NSPredicate to go along with your NSFetchRequest in order to change the correct Golfer(s).

Maybe I missed something, but this code says to me "hey, I'm going to load all of the Golfer in the database, order them by their first name, and then set all of their properties to the exact same text fields on this page". Just sounds like bad news...

To edit just one golfer, be sure to store the golfer you are editing in a property some where. Since you keep the managedObjectContext stored on the applicationDelegate, it will stay alive and thus keep your core data objects alive. That would avoid the expensive fetch that you are doing in the save view. If, however, you do not want to keep a reference to the golfer object, each NSManagedObject has an objectId, which is the identifier used by core data. You could use the objectId in a fetch predicate like so:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"objectId == %@", self.editingGolferObjectId];
[request setPredicate:predicate];

I would choose to keep reference to the object in your case, rather than the objectId

Sean Freitag
  • 930
  • 1
  • 6
  • 15
  • Thanks Sean for getting back to me. This IBAction method is to save the information (when you update golfer information like their name, email id , picture etc.) What's wrong in my code? I think i am looping them correct in executing the fetch request? – Angad Manchanda Apr 20 '12 at 02:11
  • Are you not trying to change a specific Golfer in your edit controller? How many golfers are you trying to change? – Sean Freitag Apr 20 '12 at 03:23
  • I am trying to edit a specific golfer by tapping the table view did select row method. My looping in the code is incorrect, but how do I get the index for each golfer then whom I am trying to edit? Please help me here! – Angad Manchanda Apr 20 '12 at 07:28
  • Sean, I tried just today but really can't get this to work. My post is similar to this one: http://stackoverflow.com/questions/4293026/coredata-edit-overwrite-object – Angad Manchanda Apr 22 '12 at 22:40
  • I can't help you without a greater look into your code. Perhaps you can post more code or use github? – Sean Freitag Apr 23 '12 at 01:34
  • Sean, that's the code for updating the golfers. I don't know what more to post. Can you please re-write or format my code with the aim to update a list of golfers which are displayed in a tableview, so basically update/edit records using core data? I will appreciate it. – Angad Manchanda Apr 23 '12 at 03:27
  • I cannot change what you've written, since it is fundamentally incorrect to begin with. Your controller for editing the Golfer should contain a reference to the NSManagedObject that you are editing; no NSFetchRequest should be necessary. – Sean Freitag Apr 23 '12 at 13:20
  • Sean, there is no editing controller. There is only one View Manager Controller and I have my edit View (UIView) sliding in and out of an edit button pressed method. How can I pass a reference in the same view controller which contains different UIViews. – Angad Manchanda Apr 23 '12 at 22:37
  • When you alloc and init the custom view, attach the NSManagedObject reference to it. – Sean Freitag Apr 24 '12 at 01:56
  • you mean to say use a constructor and pass that NSManagedObject as a parameter to it? – Angad Manchanda Apr 24 '12 at 02:17
  • Never Mind, I figured that out. I set up a property of a golfer and then on did select row, i used that property and in save method, fast enumeration helped in sorting out. No need of predicates here! – Angad Manchanda Apr 24 '12 at 18:18