views:

254

answers:

2

Hello,

I'm stuck trying to figure out how to modify the data contained on the persistent store. I'm writing an application with several views using a tabBarController, my core data methods are located mainly on the main application delegate but I will only be using this data from the tableViewController view.

In order to use the managedObjectContext created in the main application delegate from the tableViewController I use the following on the viewDidLoad method:

MessageAppDelegate *appDelegate = (MessageAppDelegate *)[[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];

The application then displays some messages in the table and when a user selects a UITableViewCell (didSelectRowAtIndexPath) I get the ID of the message object and call the following method:

[self readMessage:pk];
-(void)readMessage:(NSInteger)pk {  
// First I select the data
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// had to setReturnsObjectsAsFaults to NO so I could access the message data
[request setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Message" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"pk == %d", pk];
[request setPredicate:predicate];

NSError *error;
NSArray *items = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];

// Then I update the object
for (Message *thisMessage in items) {
    //I display the message to the console before updating to check the value
    DLog(@"before reading message %@", thisMessage);
    // we set the message flat to YES
    [thisMessage setRead:YES];
    // we set some sample text here (just for testing)
    [thisMessage setMessageText:@"New message text"];
    // I then display the message to the console checking that the flag and text has been updated
    DLog(@"read message %@", thisMessage);
}

// Finally I save the updated message calling the function posted below
[self saveMOC];
}

- (void)saveMOC {
 NSError *error;
 if (![managedObjectContext save:&error]) {
  NSLog(@"there was an error saving the message!");
 }
}

After that the data gets updated correctly and if I fetch the data from the managedObjectContext after saving it I get the correct values. I verified this by adding the following code to at the end of readMessage method:

    request = [[NSFetchRequest alloc] init];
//required to avoid presenting objects as faults!!
[request setReturnsObjectsAsFaults:NO];
entity = [NSEntityDescription entityForName:@"Message" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];


//Set the sort descriptor
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"pk" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];

//Execute the request
NSMutableArray *mutableFetchResults = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
    // Handle the error later
    DLog(@"ERROR: Unable to fetch the results");
}

[self setMessagesArray:mutableFetchResults];
    NSLog(@"Data now is: %@", mutableFetchResults);
[mutableFetchResults release];
[request release];

The problem is that if I exit from the application and launch it again all my messages lose the read property (or any other changes I make) and the tableview loads the data as it was first saved onto the persistent store.

Any help would be highly appreciated!! (-_-)

A: 

Try this and see if the object changes are actually being saved

- (void)saveMOC {
 NSError *error;
 if (![managedObjectContext save:&error]) {
  NSLog(@"there was an error saving the message!");
 } else {
  NSLog(@"The message was saved!");
 }
}

So for each call of saveMOC which is successful, you should see a console message. If it is being called and you're seeing the messages, then you must not be altering the 'read message' property. You could check this by inspecting the value of the 'read message' property before and after setting it either using a breakpoint or by using NSLog messages to print its value

Griffo
Hi, exactly what I've been doing ;-) I've updated the question with some more code, on the readMessage method I print the message before and after and I can see it updated fine but I must be missing something else.thanks!
unai
How are you populating the datastore originally?
Griffo
I use another method addMessage, all it does is create a new Message Object in the managedObjectContext and then sets the variables of the message (ID, text, read flag, sent date) and finally I use the saveMOC method to save it.(any new message is loaded fine after restarting the app)The strange thing is that I initially wrote this application with SQLITE functions but could not update the data neither so re-wrote it using core data this time, I wonder if there is a setting to allow SQLITE updates or something like that.
unai
So I assume if you do `[thisMessage setRead:YES];` when you create the object, it shows as read when you load the data upon opening the app, right?
Griffo
correct, it shows fine if I create the object with the flag set to YES, also I forgot to mention above that deleting the message objects works fine, only updating them doesn't work for me
unai
So, if you're able to create and delete objects, but not modify them, it's likely that the issue is a problem with how you're modifying them. Why not rewrite your update function so that it mimics the behaviour of your create function as much as possible. You must be doing something incorrectly in the way you either retrieve the object or save the change. I know thats obvious, I'm just suggesting a method by which you might find the problem
Griffo
thanks will do that and see what happens
unai
A: 

Is -readMessage: method defined in your app delegate or in your view controller? My guess is that you're changing properties of an object in different managed object context than one where you try to save changes (MOC in your app delegate), which actually doesn't have an idea that something has changed. On the other hand, MOC which keeps your changes is never saved (changes are kept only in memory) and that for your changes are lost after you restart your app.

Can this be the situation?

Matthes