views:

25

answers:

2

Two hopefully minor questions regarding CoreData that I've been unable to find answers to:

1) I have a faulted object. Accessing an attribute as a property is not firing the fault, accessing the same property via KVC IS firing the fault. Any idea why?

i.e. object.title returns nil and object is still faulted, but [object valueForKey:@"title"] returns the title and the object is no longer a fault.

2) Updates to existing records have stopped working. Add/Delete works. Add/Update share the same code path (one is passed the existing object, the other a newly inserted object). However Update wont work. The data in the updated object is correct and set to the new values and the save succeeds with no errors, but the record in the database remains unchanged. Any idea?

NB: There is only one NSManagedObjectContext

Cheers

A: 

couldn't tell much from your description without code.

however it looks like you have updated the object in ram but the update wasn't submitted to the database layer making the physical change.

EDIT:

Yes, "Add" and "Delete" is different from "edit/update" a record.

for performance reason mapped objects are saved in memory as entities when you doing manipulation against NSManagedObjectContext you are not coding against database entirely.

check the link below: http://cocoawithlove.com/2010/02/differences-between-core-data-and.html

normal work flow:

  • load appropriate rows from a database
  • instantiate objects from these rows
  • make changes to the graph objects that are now in memory
  • commit the changes back to the database
D.J
Adding a new record which goes through the same exact code path works. Updating an existing record doesn't.The Object is definitely updated in memory and save is definitely being called on the managed object context. I was hoping someone might know an obvious "gotcha".At the moment it makes absolutely no sense to me. :\
Ryan Booker
@Ryan Booker see edit above
D.J
Yeah. That's all fine. That's what I was doing already. I've solved it. As expected stupidity on my part. I converted the project to LLVM 1.5 (or 2 in Xcode 4) and added the "-Xclang -fobjc-nonfragile-abi2" flags to allow full auto generation of properties. However, when moving through the project deleting all the @synthesize calls, I also removed the @dynamic calls from my Model objects. CoreData no longer knew what to do with the memory object when saving it to the database. So the changes were lost.This also fixed point 1) above. The faults get fired as expected now.Thanks for your help
Ryan Booker
I've also just noticed that with LLVM 1.5 you need the @dynamic calls but LLVM 2 throws an error if they exist (probably why I removed them). However, it appears that LLVM 2 still needs them because updating records wont work if you remove them.
Ryan Booker
A: 

This is my core data for saving.

AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
Tweet *newTweet = (Tweet *)[NSEntityDescription insertNewObjectForEntityForName:@"Tweet" inManagedObjectContext:app.managedObjectContext];
newTweet.status = status;
newTweet.post_date = theDate;
newTweet.post_id = post_id;
newTweet.sent_error = sent_error;
newTweet.sent_status = sent_status;
newTweet.screen_name = [Settings getActiveScreenName];

// SAVE
NSError* error = nil;
if (![app.managedObjectContext save:&error]) {NSLog(@"did this work?? = %@ with userInfo = %@", error, [error userInfo]);}

I have this in my app delegate

- (void)applicationWillTerminate:(UIApplication *)application {
    // need to check if TweetViewController is activel.

    // User is writing a tweet.
    UIViewController * topController = [navigationController visibleViewController];
    if([topController isKindOfClass:[TweetViewController class]] ){
        [Settings setObject:[(TweetViewController*)topController tweetText].text forKey:@"last_tweet_text"];
    }

    NSLog(@"good bye");
    NSError *error;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Handle error.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            exit(-1);  // Fail
        } 
    }
}

and this as well in AppDelegate

/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }
    // ~/Library/Application Support/iPhone Simulator/User/
    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"tweetv12.sqlite"]];

    NSError *error;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
        // Handle error
        NSLog(@"cannot save data, change db name.");
    }    

    return persistentStoreCoordinator;
}

I am also able to save delete and update data with this.

John Ballinger