I'm using core data and i have a problem. When i save the data and the app is still running i can see and get the data that was saved.
Once the application is close, all the fields deleted and just the object is saved. I can see that in the saveContext method.
On first launch when the app is closing the saveContext method is activated. I can see that the managedObjectContext object is inserting new object.
The next times that the app is opening , the managedObjectContext is updating the object so i know it save the objects but when i try to retrive the object it can find .
here is how i insert objects:
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
#try {
UserData *userData =[NSEntityDescription insertNewObjectForEntityForName:[UserTable tableName] inManagedObjectContext:self.managedObjectContext];
//Insert Values
userData.facebookId=user.id;
userData.name=user.name;
userData.picoAccessToken=[PicoApiManager sharedInstance].accessToken;
userData.picoExpire=[PicoApiManager sharedInstance].expires;
userData.latitude=[NSNumber numberWithDouble:user.latitude];
userData.longitude=[NSNumber numberWithDouble:user.longitude];
userData.pushId=user.pushId;
userData.isActive=[NSNumber numberWithBool:activeStatus];
}
#catch (NSException *exception) {
NSLog(#"Insert exception - %#", exception.description);
}
or
-(void)addPictures:(NSMutableArray *)Pictures;
{
//Setting the isNew field to NO to all the pictures already in the db
[self updateIsNewOfPicture];
for (Picture *picture in Pictures) {
//Checks if inserted picture is already inside the table
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
#try {
PictureData *pictureData=[NSEntityDescription insertNewObjectForEntityForName:[PicturesTable tableName]inManagedObjectContext:self.managedObjectContext];
//Insert Values
pictureData.url=picture.source;
pictureData.isNew=[NSNumber numberWithBool:YES];
pictureData.isPick=[NSNumber numberWithBool:NO];
pictureData.timeTaken=picture.time_taken;
pictureData.albumData=[self getActiveAlbum];
}
#catch (NSException *exception) {
NSLog(#"Insert exception - %#", exception.description);
}
}
This is app delegate functions:
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
}
}
#pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Pico-Db" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// 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;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Pico.sqlite"];
NSError *error = nil;
_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();
}
return _persistentStoreCoordinator;
}
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
This is how i'm trying to get the data :
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
//2
// initializing NSFetchRequest
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//Setting Entity to be Queried
NSEntityDescription *entity = [NSEntityDescription entityForName:[UserTable tableName] inManagedObjectContext:appDelegate.managedObjectContext];
[fetchRequest setEntity:entity];
NSError* error;
// Query on managedObjectContext With Generated fetchRequest
NSArray *fetchedRecords = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedRecords.count >0) {
return YES;
}
return NO;
You must call -[AppDelegate saveContext] after inserting your data in order for CoreData to persist changes to disk. The NSManagedObjectContext will store changes in memory so while your application is still active, you will have access to the data. As soon as the app terminates, however, unless you call -[AppDelegate saveContext] those changes will not be persisted.
Try this in the first example:
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
#try {
UserData *userData = [NSEntityDescription insertNewObjectForEntityForName:[UserTable tableName] inManagedObjectContext:self.managedObjectContext];
//Insert Values
userData.facebookId=user.id;
userData.name=user.name;
userData.picoAccessToken=[PicoApiManager sharedInstance].accessToken;
userData.picoExpire=[PicoApiManager sharedInstance].expires;
userData.latitude=[NSNumber numberWithDouble:user.latitude];
userData.longitude=[NSNumber numberWithDouble:user.longitude];
userData.pushId=user.pushId;
userData.isActive=[NSNumber numberWithBool:activeStatus];
} #catch (NSException *exception) {
NSLog(#"Insert exception - %#", exception.description);
}
// SAVE CONTEXT:
[appDelegate saveContext];
Try this in the second example:
for (Picture *picture in Pictures) {
// Checks if inserted picture is already inside the table
AppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
#try {
PictureData *pictureData = [NSEntityDescription insertNewObjectForEntityForName:[PicturesTable tableName]inManagedObjectContext:self.managedObjectContext];
//Insert Values
pictureData.url=picture.source;
pictureData.isNew=[NSNumber numberWithBool:YES];
pictureData.isPick=[NSNumber numberWithBool:NO];
pictureData.timeTaken=picture.time_taken;
pictureData.albumData=[self getActiveAlbum];
} #catch (NSException *exception) {
NSLog(#"Insert exception - %#", exception.description);
}
}
// SAVE CONTEXT:
[appDelegate saveContext];
To create a fetch request:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"YourEntityName"];
request.sortDescriptors = [NSSortDescriptor sortDescriptorWithKey:#"attributeName" ascending:YES];
request.predicate = [NSPredicate predicateWithFormat:#"attribute == %#", 13];
NSError *error = nil; //
NSArray *results = [appDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (!results) {
NSLog(#"Error performing fetch request: %#", error.localizedDescription);
}
return ([results count] > 0); // There are more efficient ways of getting count from CoreData
Related
The belowe code works perfectly on native environment but if I use it in a Mobile first generated app it crashes. Moreover it only happens when I compile the project with iOS 10 SDK, up to iOS 9 SDK it works fine.
Message sent to deallocated instance Core Data iOS 10 Mobile First 7.1
I'm getting the following error every time I try to execute a request through NSManagedObjectContext.
*** -[_PFArray count]: message sent to deallocated instance 0x1c524f060
Here's the code:
NSError *error = nil;
NSArray *matches = [self processFetchRequest:fetchRequest error:&error];
if( matches.count > 0 ){
toReturn = (User*)[matches objectAtIndex:0];
}
where:
- (nullable NSArray*) processFetchRequest:(NSFetchRequest*)fetchRequest error:(NSError**)error{
__block NSArray *matches = nil;
#synchronized (self) {
NSManagedObjectContext *context = [self managedObjectContext];
[context performBlockAndWait:^{
matches = [context executeFetchRequest:fetchRequest error:error];
}];
}
return matches;
}
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context = _managedObjectContext;
if ( context == nil ) {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
}
return _managedObjectContext;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [self getStoreURL];
NSError *errorMetadata = nil;
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *storeOptions = #{NSPersistentStoreFileProtectionKey : NSFileProtectionCompleteUntilFirstUserAuthentication};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:storeOptions
error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
error message:
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
persistentStoreCoordinator is nil ??
------------ persistentStoreCoordinator is nil ??
- (void)updateGroupTableStatus:(TmpGroupMessageInfo*)info {
NSManagedObjectContext *ctx = [self createPrivateObjectContext];
[ctx performBlock:^{
NSPredicate *cdt = [NSPredicate predicateWithFormat:#"groupId == %# && tableId == %#", info.groupId, info.tableId];
NSFetchRequest *fetchRequest = [GroupMessageInfo makeRequest:ctx predicate:cdt orderby:nil offset:0 limit:1];
NSArray *array = [ctx executeFetchRequest:fetchRequest error:nil];
if ([array count] > 0) {
for (GroupMessageInfo *msg in array) {
msg.lastingTime = [NSNumber numberWithLongLong:0];
}
[ctx save:nil];
[self.managedObjectContext performBlock:^{
[self.managedObjectContext save:nil];
}];
}
}];
}
+ (NSFetchRequest*)makeRequest:(NSManagedObjectContext*)ctx predicate:(NSPredicate*)predicate orderby:(NSArray*)orders offset:(int)offset limit:(int)limit {
NSString *className = [NSString stringWithUTF8String:object_getClassName(self)];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:className inManagedObjectContext:ctx]];
if (predicate) {
[fetchRequest setPredicate:predicate];
}
if (orders!=nil) {
[fetchRequest setSortDescriptors:orders];
}
if (offset>0) {
[fetchRequest setFetchOffset:offset];
}
if (limit>0) {
[fetchRequest setFetchLimit:limit];
}
return fetchRequest;}
- (NSManagedObjectContext*)createPrivateObjectContext {
if (_privateManagedObjectContext == nil) {
_privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_privateManagedObjectContext setParentContext:self.managedObjectContext];
}
return _privateManagedObjectContext;
}
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"PokerSkyModel" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// 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;
}
......
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:optionsDictionary error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
[self cleanData];
abort();
}
return _persistentStoreCoordinator;
}
I came a cross exactly the same crash with yours. Finally I found out that initialize persistentStoreCoordinator of NSManagedObjectContext cannot be placed in background thread!
In your case, you do some CoreData operation at No.11 thread which is obviously not the Main Thread.If it is the first time you access your CoreData, then the persistentStoreCoordinator will be set at your No.11 background thread which lead to the crash. You can also reproduce the crash by putting these code appDidFinishLaunch at AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// your CoreData operation here
}
// ...
}
The solution is quite easy, just ensure the initialization of CoreData(or the first time you use it) should be at Main Thread.When it's not, using GCD to switch to it
dispatch_async(dispatch_get_main_queue(), 0), ^{
// your CoreData initialize here
}
I'am getting
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObject persistentStore]: unrecognized selector sent to instance 0x3bebf50'
and
while loading data from core data.I have referred links iOS Persistent store issue but it didnt solved my issue. Also data not saving to tableview.
Earlier it was loading but due to large data I've used background core data saving. but for now No data loading from DB. I'm using NSFetchResultController for fetching data.
-(void)updateThreadEntityWithSyncDetails:(NSMutableDictionary *)inDictionary
{
dispatch_queue_t backgroundQueue = dispatch_queue_create("backgroundQueueName", NULL);
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:#"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSManagedObjectContext *contextforThread = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
contextforThread.parentContext = context;
[contextforThread performBlock:^{
// AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ThreadInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:#"userEmail == %#",loginUser];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:#"threadID == %#",[inDictionary valueForKey:#"thread"]];
NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: #[userPredicate, threadPredicate]];
[fetchRequest setPredicate:compoundPredicate];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:nil];
for (ThreadInfo *threadInfo in fetchedObjects)
{
if([[inDictionary allKeys] containsObject:#"userEmail"])
{
if([inDictionary valueForKey:#"userEmail"]!=[NSNull null])
{
threadInfo.userEmail=[inDictionary valueForKey:#"userEmail"];
}
}
if([[inDictionary allKeys] containsObject:#"secret_seed"])
{
if([inDictionary valueForKey:#"secret_seed"]!=[NSNull null])
{
threadInfo.threadSecret=[NSString stringWithFormat:#"%#",[inDictionary valueForKey:#"secret_seed"]];
}
}
if([[inDictionary allKeys] containsObject:#"r_key"])
{
if([inDictionary valueForKey:#"r_key"]!=[NSNull null])
{
threadInfo.remoteKey=[inDictionary valueForKey:#"r_key"];
}
}
if([[inDictionary allKeys] containsObject:#"solicitation"])
{
if([inDictionary valueForKey:#"solicitation"]!=[NSNull null])
{
threadInfo.solicitationID=[inDictionary valueForKey:#"solicitation"];
}
}
if([[inDictionary allKeys] containsObject:#"r_secret"])
{
if([inDictionary valueForKey:#"r_secret"]!=[NSNull null])
{
threadInfo.remoteSecret=[inDictionary valueForKey:#"r_secret"];
}
}
NSError *error;
if (![contextforThread save:&error]) {
NSLog(#"Could not insert to userInfo: %#", [error localizedDescription]);
}
[context performBlock:^{
NSError *error;
if (![context save:&error]) {
NSLog(#"Could not insert to userInfo: %#", [error localizedDescription]);
}
}];
}];
// if (![context save:&error]) {
// NSLog(#"Could not update to threadInfo: %#", [error localizedDescription]);
// }
}
Appdelegate
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
// _managedObjectContext = [[NSManagedObjectContext alloc] init];
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"IXCoreDataModel" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Inxed.sqlite"];
NSError *error = nil;
_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();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
FetchedResultsController
-(NSFetchedResultsController*)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:#"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ThreadInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"threadDate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:#"userEmail == %#",loginUser];
// NSPredicate *providerPredicate = [NSPredicate predicateWithFormat:#"isReceiver == YES"];
// NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: #[threadPredicate, providerPredicate]];
[fetchRequest setPredicate:threadPredicate];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:nil
cacheName:nil];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
CRASH CODE
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
ThreadInfo *info=[_fetchedResultsController objectAtIndexPath:indexPath];
if([info.isSystemMessage boolValue])// CRASH CoreData: error: NULL _cd_rawData but the object is not being turned into a fault
{
return 178+90+25;
} else {
return 178;
}
getting
CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Only run on the main thread! with userInfo (null)
When scrolling to last cell, I'm getting this crash too with nothing in the cell.
Make sure you save your contexts in performBlock method like
[mainContext performBlock^{
[mainContext save:&error];
}];
Also refer this thread
This is My code:
This is iCloud with Coredata synchronization configuration code:
#pragma mark - Core Data stack
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "com.wanglichen.iPassword" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"iPassword" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// create a new persistent store of the appropriate type
NSError *error = nil;
NSURL *storeURL = [self applicationDocumentsDirectory];
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
// ** Note: if you adapt this code for your own use, you MUST change this variable.
// is the full App ID (including the Team Prefix). You will need to change this to match the Team Prefix found in your own iOS Provisioning Portal.
NSString *iCloudEnabledAppID = [[NSBundle mainBundle] infoDictionary][#"CFBundleIdentifier"];
// the name of the SQLite database store file.
NSString *dataFileName = #"iPassword.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
// dataDirectory is the name of the directory the database will be stored in. It should always end with .nosync
// iCloudData = iCloudRootPath + dataDirectory
NSString *iCloudDataDirectoryName = #"Data.nosync";
// logsDirectory is the name of the directory the database change logs will be stored in.
NSString *iCloudLogsDirectoryName = #"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localStore = [storeURL URLByAppendingPathComponent:dataFileName];
// iCloudRootPath is the URL to your apps iCloud root path.
NSURL *iCloudRootPath = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloudRootPath) // If iCloud is working, save it to iCloud container.
{
NSLog(#"iCloud is working.");
// Place core data sqlite file in iCloudRootPath/Data.nosync/ (The subdirectory should be ended with .nosync)
// Place the log file in iCloudRootPath/Logs (All changed in iCloud will be download to log file firstly.)
NSURL *iCloudLogsPath = [iCloudRootPath URLByAppendingPathComponent:iCloudLogsDirectoryName];
// NSLog(#"iCloudEnabledAppID = %#",iCloudEnabledAppID);
// NSLog(#"dataFileName = %#", dataFileName);
// NSLog(#"iCloudDataDirectoryName = %#", iCloudDataDirectoryName);
// NSLog(#"iCloudLogsDirectoryName = %#", iCloudLogsDirectoryName);
// NSLog(#"iCloud = %#", iCloudRootPath);
// NSLog(#"iCloudLogsPath = %#", iCloudLogsPath);
NSURL *iCloudDataURL = [iCloudRootPath URLByAppendingPathComponent:iCloudDataDirectoryName];
if ([fileManager fileExistsAtPath:[iCloudDataURL path]] == NO)
{
NSError *fileSystemError;
[fileManager createDirectoryAtPath:[iCloudDataURL path]
withIntermediateDirectories:YES
attributes:nil
error:&fileSystemError];
if(fileSystemError != nil)
{
NSLog(#"Error creating database directory %#", fileSystemError);
}
}
iCloudDataURL = [iCloudDataURL URLByAppendingPathComponent:dataFileName];
// NSLog(#"iCloudDataPath = %#", iCloudDataURL);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:#(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:#(YES) forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];
[_persistentStoreCoordinator lock];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:iCloudDataURL
options:options
error:nil])
{
NSDictionary *ui = [error userInfo];
for(NSString *err in [ui keyEnumerator]) {
NSLog(#"err:%#",[ui objectForKey:err]);
}
abort();
}
[_persistentStoreCoordinator unlock];
}
else // If iCloud is not working, save it to local.
{
NSLog(#"iCloud is NOT working - using a local store");
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:#(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:#(YES) forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:#(YES) forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:#(YES) forKey:NSInferMappingModelAutomaticallyOption];
[_persistentStoreCoordinator lock];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil])
{
NSDictionary *ui = [error userInfo];
for(NSString *err in [ui keyEnumerator]) {
NSLog(#"err:%#",[ui objectForKey:err]);
}
abort();
}
[_persistentStoreCoordinator unlock];
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
// Register NSPersistentStoreDidImportUbiquitousContentChangesNotification, so that
// coreDataChangedIniCloud will be called if core data in iCloud is changed.
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(coreDataChangedIniCloud:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:self.persistentStoreCoordinator];
return _managedObjectContext;
}
- (void)coreDataChangedIniCloud:(NSNotification *)notification
{
NSLog(#"Merging in changes from iCloud...");
[self.managedObjectContext performBlock:^{
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
NSLog(#"new data from iCloud: %#", notification.object);
[[NSNotificationCenter defaultCenter] postNotificationName:#"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
}];
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
Here is the problem I encountered:
Crash mark
When iCloud data inside the change, I call the following method:
- (void)coreDataChangedIniCloud:(NSNotification *)notification
{
NSLog(#"Merging in changes from iCloud...");
[self.managedObjectContext performBlock:^{
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
NSLog(#"new data from iCloud: %#", notification.object);
[[NSNotificationCenter defaultCenter] postNotificationName:#"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
}];
}
This is the cause of the crash:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can only use -performBlock: on an NSManagedObjectContext that was created with a queue.
performBlock (and performBlockAndWait) can only be used for NSManagedObjectContexts that were initialised with either NSPrivateQueueConcurrencyType or NSMainQueueConcurrencyType. By default NSManagedObjectContexts are initialised to use the NSConfinementConcurrencyType which does not support performBlock or performBlockAndWait.
You should change this line:
_managedObjectContext = [[NSManagedObjectContext alloc] init];
to either:
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
or
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
Try this.
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
- (void)coreDataChangedIniCloud:(NSNotification *)notification
NSManagedObjectContext *moc = self.managedObjectContext;
[moc performBlockAndWait:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MergingInChangesFromICloud" object:notification.object userInfo:[notification userInfo]];
});
}
I'm creating an object with the following code:
+(Checkin *) newCheckinWithId:(NSString*) checkinID forVenueId:(NSString *)venueId
{
NSManagedObjectContext * context = [[AppDelegate sharedInstance] managedObjectContext];
Checkin *ret = (Checkin *)[NSEntityDescription insertNewObjectForEntityForName:#"Checkin" inManagedObjectContext:context];
ret.checkinID = checkinID;
ret.forVenueID = venueId;
ret.date = [NSDate date];
NSError * error;
if(![context save:&error]) {
NSLog(#"Error saving!!!!!: %#", error.userInfo);
}
return ret;
}
This code works, and I can see the objects in the sqldatabase file on disk (in ~/library/iphone sim/.. whatever it is)
Here is the code I use to create my store + managed object context (I use 1 context for everything) Its basically all from a stack overflow post I found
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil)
{
return _managedObjectModel;
}
//NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Model" withExtension:#"momd"];
//__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
//NSArray *testArray = [[NSBundle mainBundle] URLsForResourcesWithExtension:#"momd"subdirectory:nil];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Model" ofType:#"momd"];
if( !path ) path = [[NSBundle mainBundle] pathForResource:#"Model" ofType:#"mom"];
NSURL *modelURL = [NSURL fileURLWithPath:path];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
//__managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if((_persistentStoreCoordinator != nil)) {
return _persistentStoreCoordinator;
}
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSPersistentStoreCoordinator *psc = _persistentStoreCoordinator;
// Set up iCloud in another thread:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// ** Note: if you adapt this code for your own use, you MUST change this variable:
NSString *iCloudEnabledAppID = #"[MY APP ID]";
// ** Note: if you adapt this code for your own use, you should change this variable:
NSString *dataFileName = #"foursquareaugmentation.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
NSString *iCloudDataDirectoryName = #"Data.nosync";
NSString *iCloudLogsDirectoryName = #"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloud) {
NSLog(#"iCloud is working");
NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];
NSLog(#"iCloudEnabledAppID = %#",iCloudEnabledAppID);
NSLog(#"dataFileName = %#", dataFileName);
NSLog(#"iCloudDataDirectoryName = %#", iCloudDataDirectoryName);
NSLog(#"iCloudLogsDirectoryName = %#", iCloudLogsDirectoryName);
NSLog(#"iCloud = %#", iCloud);
NSLog(#"iCloudLogsPath = %#", iCloudLogsPath);
if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
NSError *fileSystemError;
[fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
withIntermediateDirectories:YES
attributes:nil
error:&fileSystemError];
if(fileSystemError != nil) {
NSLog(#"Error creating database directory %#", fileSystemError);
}
}
NSString *iCloudData = [[[iCloud path]
stringByAppendingPathComponent:iCloudDataDirectoryName]
stringByAppendingPathComponent:dataFileName];
NSLog(#"iCloudData = %#", iCloudData);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[options setObject:iCloudEnabledAppID forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setObject:iCloudLogsPath forKey:NSPersistentStoreUbiquitousContentURLKey];
[psc lock];
NSError *error;
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:[NSURL fileURLWithPath:iCloudData]
options:options
error:&error];
if( error )
{
NSLog(#"Error adding persistent store %#, %#", error, [error userInfo]);
// comment in this line while debugging if get "Can't find model for source store" error in addPersistentStoreWithType.
// it means the sqlite database doesn't match the new model and needs to be created from scratch.
// this happens if you change the xcdatamodel instead of creating a new one under Xcode->Editor->Add Model Version...
// CoreData can only automatically migrate if there is a new model version (it can't migrate if the model simply changes, because it can't see the difference between the two models).
// be sure to back up the database if needed, because all data will be lost.
//[fileManager removeItemAtPath:iCloudData error:&error];
/*// this is another way to verify the hashes for the database's model to make sure they match one of the entries in the momd directory's VersionInfo.plist
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:[NSURL fileURLWithPath:iCloudData] error:&error];
if( !sourceMetadata )
NSLog(#"sourceMetadata is nil");
else
NSLog(#"sourceMetadata is %#", sourceMetadata);*/
}
[psc unlock];
}
else {
NSLog(#"iCloud is NOT working - using a local store");
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[psc lock];
NSError *error;
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil];
if( error )
NSLog(#"Error adding persistent store %#, %#", error, [error userInfo]);
[psc unlock];
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"SomethingChanged" object:self userInfo:nil];
});
});
return _persistentStoreCoordinator;
}
/*
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *) managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator: coordinator];
}
return _managedObjectContext;
}
Here is my fetch:
+(NSArray *) checkinsForVenue:(NSString *) venueID
{
NSManagedObjectContext * context = [[AppDelegate sharedInstance] managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Checkin" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = entity;
//NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(forVenueID = %#)", venueID];
//request.predicate = predicate;
NSError *error;
NSArray * ret = [context executeFetchRequest:request error:&error];
if(ret == nil) {
NSLog(#"%#", error.description);
}
return ret;
}
Fetch always returns no objects (the empty array) even though there are things in the database!
I've been working on this problem for quiet a while and am pretty out of ideas so anything appreciated!
Thanks
Try this code to fetch data:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil )
{
return _fetchedResultsController;
}
NSLog(#"Length:: %d",[[_fetchedResultsController mutableCopy] length]);
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"OrderDetails"];
[fetchRequest setIncludesSubentities:YES];
// Sort by Application name
NSSortDescriptor* sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:#"orderId" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
//Sort by CommandNameloca
NSArray* sortDescriptors = [[NSArray alloc] initWithObjects: sortDescriptor1, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setFetchBatchSize:100];
ordersArr=[[NSMutableArray alloc]initWithArray:sortDescriptors];
NSLog(#"----- ordersArr Count == %d",[ordersArr count]);
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"orderId" cacheName:#"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
After this method i executed write this line to store data in your app array like this:
NSMutableArray *myArr=[[NSMutableArray alloc]initWithArray:self.fetchedResultsController.fetchedObjects];