saving managedObjectContext returns null error - iphone

Could anyone see any possible reasons why?
Friend *newFriend = [NSEntityDescription insertNewObjectForEntityForName:#"Friend" inManagedObjectContext:managedObjectContext];
newFriend.name = #"Jim";
newFriend.age = [NSNumber numberWithInt:5];
NSError *error = nil;
if ([managedObjectContext save:&error])
{
NSLog(#"error %#", error);
}
managedObjectContext was passed to the view controller where this code is from the application delegate.
Thanks

if (![managedObjectContext save:&error])
{
NSLog(#"error %#", error);
}
that should be

You should expect error to continue to be nil if save: succeeded (and therefore returned YES as you're testing). What behavior did you expect here?

Related

MagicalRecord save causes EXC_BAD_ACCESS

I am having issues when I try to do "save" with MagicalRecord. My code:
- (void) findInternetObject {
[InternetObjectFinder runBlockSuccess:^(NSManagedObject *obj) {
obj.attr1 = #"abc";
[[NSManagedObjectContext MR_defaultContext] MR_saveErrorHandler:^(NSError *error) {
NSLog(#"failed to save attr1, Error: %#, %#", error.localizedDescription, error.userInfo);
}];
}];
}
where obj was created in method "runBlockSuccess" method in "InternetObjectFinder" class:
InternetObject *obj = [InternetObject MR_createEntity];
The app crashes at line:
[NSManagedObjectContext MR_defaultContext] MR_saveErrorHandler
with error: EXC_BAD_ACCESS
Any help is appreciated.
It seems to be a scope issue inside your nested blocks,
have you tried to write something like this (not tested):
- (void) findInternetObject {
NSManagedObjectContext *defaultContext = [NSManagedObjectContext MR_defaultContext];
[InternetObjectFinder runBlockSuccess:^(NSManagedObject *obj) {
obj.attr1 = #"abc";
[defaultContext MR_saveErrorHandler:^(NSError *error) {
NSLog(#"failed to save attr1, Error: %#, %#", error.localizedDescription, error.userInfo);
}];
}];
}
If the proble persist maybe this detailed answer can help you:
How do I avoid capturing self in blocks when implementing an API?
You should call save method on main thread. Your code looks that you are saving core data into block. If that doesn't work you can use below code to save.
MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
} completion:^(BOOL success, NSError *error) {
if(success){
NSLog(#"success");
}
}];

fetchcontroller is not getting value in facebook chat ios app

I have deleted all of the entries stored in Core Data at the time of logout in my FBChat application by using the methods as follows.
//delete persistance.......
if ([__persistentStoreCoordinator persistentStores] == nil)
return;
[self.managedObjectContext reset];
[self.managedObjectContext lock];
NSPersistentStore *store = [[self.persistentStoreCoordinator persistentStores] lastObject];
if (![self.persistentStoreCoordinator removePersistentStore:store error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
// Delete file
if ([[NSFileManager defaultManager] fileExistsAtPath:store.URL.path]) {
if (![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
__persistentStoreCoordinator = nil;
__persistentStoreCoordinator = [self persistentStoreCoordinator];
[self.managedObjectContext unlock];
But When I am log in again, fetchcontroller not getting the values. I have set the fetchcontroller=nil while logout. The delegate methods for the fetchcontroller are getting called at the login time.
If anybody having idea then please help me. Thanks in advance
This is expected behavior. After deleting everything, you are not getting values. If your fetched results controller is created lazily (code not shown, but that is usually the design pattern), it will create itself when needed.
No surprises here.

Core Data issue - checking if item exists

I am working on a code example from NSScreenCast that deals with importing to a Core Data application (link). I have the example working for the most part. I am able to push the refresh button, it parses the json and imports it in to the database. However, every time I press the refresh button it re-adds the same data. I have traced it down to the following code.
+ (Brewery *)breweryWithServerId:(NSInteger)serverId usingManagedObjectContext:(NSManagedObjectContext *)moc {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[Brewery entityName]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"serverId = %d", serverId]];
[fetchRequest setFetchLimit:1];
NSError *error = nil;
NSArray *results = [moc executeFetchRequest:fetchRequest error:&error];
NSLog(#"results: %#", results);
if (error) {
NSLog(#"ERROR: %# %#", [error localizedDescription], [error userInfo]);
exit(1);
}
if ([results count] == 0) {
return nil;
}
NSLog(#"results objectAtIndex:0 = %#", [results objectAtIndex:0]);
return [results objectAtIndex:0];
}
What happens is this method is that it tries to see if the item already exists in the database. If this call returns nil, then the code in MasterViewController adds it again to the database. I have done some debugging and the serverId does get passed. Also, the fetchrequest seems to be valid (haven't been able to debug it to be sure). As you can see I have put a NSLog for the results, but it returns an empty result. So, it then goes to if the results count is 0 which it is, it returns nil. Thus my issue. I don't see any where else where this issue could be a problem. Any thoughts?
Mike Riley
I just modified your method, you can just take a try:
+ (Brewery *)breweryWithServerId:(NSInteger)serverId usingManagedObjectContext:(NSManagedObjectContext *)moc {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[Brewery entityName]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"serverId == %d", serverId]];
[fetchRequest setFetchLimit:1];
NSError *error = nil;
// if there's no object fetched, return nil
if ([managedObjectContext countForFetchRequest:fetchRequest error:&error] == 0) {
NSLog(#"!!!WARN: NO Object Matches.");
return nil;
}
// fetch your object
Brewery *result = [[moc executeFetchRequest:fetchRequest error:&error] lastObject];
if (error != nil) {
NSLog(#"ERROR: %# %#", [error localizedDescription], [error userInfo]);
return nil;
}
NSLog(#"results objectAtIndex:0 = %#", result);
return result;
}
Note: -countForFetchRequest:error: is more efficient as it only 'returns the number of objects a given fetch request would have returned'. You can use this method to check whether there's a object that matches.
You're trying to compare a scalar value (NSInteger) with an object value (NSNumber) in your predicate.
Try:
[NSPredicate predicateWithFormat:#"serverId = %#", [NSNumber numberWithInteger:serverId]]
I think there is a problem in your predicate. It should read:
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"serverId == %d", serverId]];
You missed the double equals....
Found out it doesn't matter. You should check to make sure your moc is not nil. Are you sure you're passing it in correctly?

"[CFString release]: message sent to deallocated instance" when using CoreData

I have started using CoreData in my project. Without the pieces of code from CodeData my project was working pretty fine. I added the methods for accessing the NSManagedObjectContext from the coreData project template. Now I try to create new CoreData object with the following code:
- (void)saveSearchResultToHistory:(NSArray *) productsArray {
[productsArray retain];
NSLog(#"context: %#", self.managedObjectContext);
Product *product = [NSEntityDescription
insertNewObjectForEntityForName:#"Product"
inManagedObjectContext:self.managedObjectContext];
product.productId = [(Product *) [productsArray objectAtIndex:0] productId];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
[productsArray release];
}
When this method is ran once then everything is fine, when I try to run it for the second time, the processing is stopped at:
Product *product = [NSEntityDescription
insertNewObjectForEntityForName:#"Product"
inManagedObjectContext:self.managedObjectContext];
with the following error message in the console:
[CFString retain]: message sent to deallocated instance 0x5a23b0
Any ideas what might be wrong?
Thanks!
First off you do not need to save the context every time you add something, just save when the app closes or goes in the background.
The error you are getting looks like you over release a NSString some where.
To check if the error isn't in the coredata context use this save function:
- (void)saveContext {
if ([self.managedObjectContext hasChanges]) {
NSError *error = nil;
if (![self.managedObjectContext save:&error]) {
dbgPrint(#"Failed to save to data store: %#", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if (detailedErrors != nil && [detailedErrors count] > 0) {
for(NSError* detailedError in detailedErrors) {
dbgPrint(#"--DetailedError: %#", [detailedError userInfo]);
}
} else {
dbgPrint(#" %#", [error userInfo]);
}
}
}
}

Core data: Why removing the sqlite file did not clear all the previous data insert immediately?

I want to reset the data store clean by removing the app's sqlite file. I wrote this function in my data helper class:
-(void) resetPersistenStore {
NSError *error = nil;
[persistentStoreCoordinator_ release];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"MyApp.sqlite"];
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
if (error) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
managedObjectModel_ = nil;
}
I put this following test in UIApplication::didFinishLaunchingWithOptions
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/* test */
[TestDataHelper populateTestData:[self managedObjectContext]];
[TestDataHelper populateTestData:[self managedObjectContext]];
[self resetPersistenStore];
[TestDataHelper populateTestData:[self managedObjectContext]];
[TestDataHelper testPopulateTestData:[self managedObjectContext]];
Instead of one set of data created by the function populateTestData, I can see actually three set of data (because I called the function three times)
It is clear that resetPersistenStore() works, because without it, the data will keep accumulating.
So my question is:
Why the reset does not take effect immediately?
I have set managedObjectContext to nil in the reset function, but it did not help.
Here is my populateTestData function
+(void)populateTestData:(NSManagedObjectContext*)managedObjectContext {
Stock* s1 = (Stock*)[NSEntityDescription insertNewObjectForEntityForName:#"Stock"
inManagedObjectContext:managedObjectContext];
s1.code = #"ABC2";
s1.name = #"ABC";
s1.enteredBy = #"akong";
[managedObjectContext save:&error];
if (error) {
NSLog(#"Data error %#", [error description]);
} else {
NSLog(#"Init completed");
}
}
Even though the context saved the data in populateTestData, it still has data loaded in it.
Suppose when the application starts, the file has 3 objects. Now the first populateTestData message adds an object into the context, and save it. So 4 objects in the file, 1 in the context. After the second message, 5 in the file, 2 in the context. Now the file is gone, but still there are 2 in the context. Now the final message adds another object to the context and to the file, so there are 3 objects.
You said setting managedObjectContext to nil in the reset function didn't help. I doubt if the context has been properly reset there. Try [managedObjectContext reset] instead.
I am only speculating here but are you by any chance using a fetchedResultsController to verify/display the results of these operations? If so try to set its caching to nil and see if it helps.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"xxxxxxxx" cacheName:nil];
Cheers,
Rog
It may simply be an artifact of the simulator. If you're running in the simulator, you may need to reset it. From the iOS Simulator menu, select Reset Content and Settings...