I have my app set up to use core data with iCloud, but when it starts, the UITableView showing the data is empty, and takes a moment to fill with data. Is there any way to get it to display the data immediately, as if it didn't have iCloud integration?
- (NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[moc performBlockAndWait:^{
[moc setPersistentStoreCoordinator: coordinator];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
}];
managedObjectContext = moc;
managedObjectContext.mergePolicy = [[NSMergePolicy alloc]
initWithMergeType:NSMergeByPropertyObjectTrumpMergePolicyType];
}
return managedObjectContext;
}
- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {
NSLog(#"Merging in changes from iCloud...");
NSManagedObjectContext* moc = [self managedObjectContext];
[moc performBlock:^{
[moc mergeChangesFromContextDidSaveNotification:notification];
NSNotification* refreshNotification = [NSNotification notificationWithName:#"SomethingChanged"
object:self
userInfo:[notification userInfo]];
[[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
}];
}
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
NSString *modelPath = [[NSBundle mainBundle] pathForResource:#"EntryDatabase" ofType:#"momd"];
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
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 = #"IDRemovedFromStackOverflow";
// ** Note: if you adapt this code for your own use, you should change this variable:
NSString *dataFileName = #"CoreDataStore.sqlite";
// ** Note: For basic usage you shouldn't need to change anything else
NSString *iCloudDataDirectoryName = #"Data.nosync";
NSString *iCloudLogsDirectoryName = #"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:dataFileName];
NSURL *localStore = [NSURL fileURLWithPath:storePath];
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];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:[NSURL fileURLWithPath:iCloudData]
options:options
error:nil];
[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];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil];
[psc unlock];
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:#"SomethingChanged" object:self userInfo:nil];
});
});
return persistentStoreCoordinator;
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
//Set up the fetched results controller.
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Entry" inManagedObjectContext:[AppDelegate applicationDelegate].managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Sort using the timeStamp property..
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"creationDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Use the sectionIdentifier property to group into sections.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[AppDelegate applicationDelegate].managedObjectContext sectionNameKeyPath:#"sectionIdentifier" cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
self.fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
A possible solution would be to create a prepopulated .sqlite-file to your bundle, and copy it to the Documents directory just before creating the persistent store coordinator
Related
My coredata methods are here. How to write unit test case to check this.
Method to save to coredata
- (void)saveUserDetails:(Model *)userDetail {
if(userDetail != nil) {
UserEntity *user = [NSEntityDescription insertNewObjectForEntityForName:#“EntityName” inManagedObjectContext:[self sharedContext]];
NSArray *fetchArray = [self fetchUserWithUsername:userDetail.username];
if ([fetchArray count] == 0) {
user.username = userDetail.username;
[self saveContext];
}
}
}
Method to fetch from coredata
- (NSArray *)fetchUserWithUsername:(NSString *)username {
if (username != nil) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *userEntity = [NSEntityDescription entityForName:#“EntityName” inManagedObjectContext:[self sharedContext]];
[fetchRequest setEntity:userEntity];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"username = %#", username];
NSError *error;
NSArray *fetchedObjects = [[self sharedContext] executeFetchRequest:fetchRequest error:&error];
return fetchedObjects;
}
return nil;
}
Create an in-memory store and inject this into your object.
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"MyResource" withExtension:#"momd"];
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
XCTAssertTrue([psc addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:NULL] ? YES : NO, #"Should be able to add in-memory store");
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = psc;
Thanks in advance for the help and be understanding if i write strange things i'm new in objective-c language.
I get json from web service and trying to store all in core-data so in case of network status off can i run app whit saved data.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.managedObjectContext = [self managedObjectContextWithName:#"CoreData"];
NSMutableArray * competition = [self.jsonCompetition objectForKey:#"Competition"];
NSMutableDictionary * competizione = [[NSMutableDictionary alloc] init];
for (int i = 0; i< competition.count; i++) {
NSManagedObject * competion = [NSEntityDescription
insertNewObjectForEntityForName:#"Competition"
inManagedObjectContext:self.managedObjectContext];
competizione = [competition objectAtIndex:i];
[competion setValue:[competizione objectForKey:#"id"] forKeyPath:#"id"];
[competion setValue:[competizione objectForKey:#"name"] forKeyPath:#"name"];
[competion setValue:[competizione objectForKey:#"region"] forKeyPath:#"region"];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Errore: %#", [error localizedDescription]);
}
}
NSError *errore;
if (!errore) {
// NSLog(#"%#",_jsonDict);
} else {
NSLog(#"ERROR!");
}
[self.managedObjectContext save:&errore];
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
if (networkStatus == ReachableViaWWAN) {
} else if (networkStatus == ReachableViaWiFi) {
NSData *data = [self callWS];
NSError *errore;
self.jsonCompetition = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions
error:&errore];
self.managedObjectContext = [self managedObjectContextWithName:#"CoreData"];
NSMutableArray * competition = [self.jsonCompetition objectForKey:#"Competition"];
NSMutableDictionary * competizione = [[NSMutableDictionary alloc] init];
for (int i = 0; i< competition.count; i++) {
NSManagedObject * competion = [NSEntityDescription
insertNewObjectForEntityForName:#"Competition"
inManagedObjectContext:self.managedObjectContext];
competizione = [competition objectAtIndex:i];
[competion setValue:[competizione objectForKey:#"id"] forKeyPath:#"id"];
[competion setValue:[competizione objectForKey:#"name"] forKeyPath:#"name"];
[competion setValue:[competizione objectForKey:#"region"] forKeyPath:#"region"];
if (![self.managedObjectContext save:&errore]) {
NSLog(#"Errore: %#", [errore localizedDescription]);
}
}
[self.managedObjectContext save:&errore];
if (!error) {
// NSLog(#"%#",_jsonDict);
} else {
NSLog(#"ERROR!");
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityCompetizione = [NSEntityDescription
entityForName:#"Competition" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityCompetizione];
NSArray *arrayCompetizioni = [self.managedObjectContext executeFetchRequest:fetchRequest error:&errore];
} else {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityCompetizione = [NSEntityDescription
entityForName:#"Competition" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityCompetizione];
NSArray *arrayCompetizioni = [self.managedObjectContext executeFetchRequest:fetchRequest error:&errore];
}
FirstViewController * fVC = [[FirstViewController alloc]initWithNibName:#"FirstViewController" bundle:nil];
self.window.rootViewController = fVC;
[self.window makeKeyAndVisible];
return YES;
In json i have a key whit ApiVersion,there is a way to check if core-data need to be updated whit the new version of json (in case of network status is on )??
thanks
You save the previous ApiVersion to NSUserDefaults:
NSNumber *currentApiVersion = ...; //You get the version here from JSON
[[NSUserDefaults standardUserDefaults] setObject:currentApiVersion forKey:#"ApiVersion"];
When new data arrives, you compare with the saved value:
NSNumber *currentApiVersion = ...; //You get the version here from the JSON
NSNumber *previousApiVersion = [[NSUserDefaults standardUserDefaults] objectForKey:#"ApiVersion"];
if (![currentApiVersion isEqualToNumber:previousApiVersion]) {
//Update the stored version
[[NSUserDefaults standardUserDefaults] setObject:currentApiVersion forKey:#"ApiVersion"];
//The Api Version is different.
}
I have a project where I'm consuming data from several web services and then storing them in separate entities in Core Data. To be precise there are 4 different entities. 3 of them are storing just fine. The 4th stores in Core Data and I can retrieve it later in other views but if I close the app and open it back up the InventoryImage Entity seems to be empty.
- (void)viewDidLoad {
[super viewDidLoad];
id delegate = [[UIApplication sharedApplication]delegate];
self.managedObjectContext = [delegate managedObjectContext];
_isConnected = TRUE;
[self checkOnlineConnection];
DealerModel *dealer = [[DealerModel alloc]init];
[dealer getDealerNumber];
_dealerNumber = dealer.dealerNumber;
//_dealerNumber = #"000310";
if (_isConnected == TRUE) {
[self downloadInventoryData:_dealerNumber];
[self downloadImages:_dealerNumber];
}
else{
[self loadInventory];
[self loadImages];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/* Table Data */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_modelsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
InventoryCell *cell = (InventoryCell *)[tableView dequeueReusableCellWithIdentifier:[_inventoryCell reuseIdentifier]];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"InventoryCell" owner:self options:nil];
cell = _inventoryCell;
_inventoryCell = nil;
}
InventoryHome *currentHome = [_modelsArray objectAtIndex:indexPath.row];
NSNumber *imageCount = [self loadImagesBySerialNumber:currentHome.serialNumber];
cell.lblModelDescription.text = currentHome.homeDesc;
cell.lblSerialNumber.text = currentHome.serialNumber;
cell.lblImageCount.text = [NSString stringWithFormat:#"Images: %#", imageCount];
return cell;
}
/* End Table Data */
/* Start Downloads */
#pragma mark - Inventory and Image Data
- (void)downloadInventoryData:(NSString *)dealerNumber
{
[self loadInventory];
if (_isConnected == 1 && [_modelsArray count] > 0) {
[self clearModelEntity:#"InventoryHome"];
}
NSString *urlString = [NSString stringWithFormat:#"%#%#", webServiceInventoryListURL, dealerNumber];
NSURL *invURL = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:invURL];
NSLog(#"Inventory Web Service URL: %#", invURL);
// Sticks all of the jSON data inside of a dictionary
_jSON = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Creates a dictionary that goes inside the first data object eg. {data:[
_dataDictionary = [_jSON objectForKey:#"data"];
// Check for other dictionaries inside of the dataDictionary
for (NSDictionary *modelDictionary in _dataDictionary) {
InventoryHome *home = [NSEntityDescription insertNewObjectForEntityForName:#"InventoryHome" inManagedObjectContext:[self managedObjectContext]];
NSString *trimmedSerialNumber = [NSString stringWithFormat:#"%#",[NSLocalizedString([modelDictionary objectForKey:#"serialnumber"], nil) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
home.homeDesc = NSLocalizedString([modelDictionary objectForKey:#"description"], nil);
home.serialNumber = trimmedSerialNumber;
home.brandDesc = NSLocalizedString([modelDictionary objectForKey:#"branddescription"], nil);
home.beds = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"numberofbedrooms"], nil) intValue]];
home.baths = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"numberofbathrooms"], nil) intValue]];
home.sqFt = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"squarefeet"], nil) intValue]];
home.length = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"length"], nil) intValue]];
home.width = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"width"], nil) intValue]];
}
[self loadInventory];
}
- (void)downloadImages:(NSString *)dealerNumber
{
[self loadImages];
if (_isConnected == 1 && [_imagesArray count] > 0) {
[self clearModelEntity:#"InventoryImage"];
}
NSString *stringImageURL = [NSString stringWithFormat:#"%#%#",inventoryImageURL, dealerNumber];
NSURL *url = [NSURL URLWithString:stringImageURL];
NSData *imageData = [NSData dataWithContentsOfURL:url];
_jSON = [NSJSONSerialization JSONObjectWithData:imageData options:kNilOptions error:nil];
_dataDictionary = [_jSON objectForKey:#"data"];
for (NSDictionary *imageDictionary in _dataDictionary) {
InventoryImage *image = [NSEntityDescription insertNewObjectForEntityForName:#"InventoryImage" inManagedObjectContext:[self managedObjectContext]];
NSString *trimmedSerialNumber = [NSString stringWithFormat:#"%#",[NSLocalizedString([imageDictionary objectForKey:#"serialnumber"], nil) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
image.assetID = NSLocalizedString([imageDictionary objectForKey:#"aid"], nil);
image.sourceURL = NSLocalizedString([imageDictionary objectForKey:#"imagereference"], nil);
image.serialNumber = trimmedSerialNumber;
image.group = NSLocalizedString([imageDictionary objectForKey:#"imagegroup"], nil);
image.imageTagId = [NSString stringWithFormat:#"%#", [imageDictionary objectForKey:#"searchtagid"]];
image.imagesId = [NSString stringWithFormat:#"%#", [imageDictionary objectForKey:#"imagesid"]];
image.imageCaption = NSLocalizedString([imageDictionary objectForKey:#"imagecaption"], nil);
image.imageSource = NSLocalizedString([imageDictionary objectForKey:#"imagesource"], nil);
image.inventoryPackageID = NSLocalizedString([imageDictionary objectForKey:#"inventorypackageid"], nil);
}
}
/* End Downloads */
/* Load Inventory and Image From Core Data */
- (void)loadInventory
{
_fetchRequest = [[NSFetchRequest alloc]init];
_entity = [NSEntityDescription entityForName:#"InventoryHome" inManagedObjectContext:[self managedObjectContext]];
_sort = [NSSortDescriptor sortDescriptorWithKey:#"homeDesc" ascending:YES];
_sortDescriptors = [[NSArray alloc]initWithObjects:_sort, nil];
[_fetchRequest setSortDescriptors:_sortDescriptors];
[_fetchRequest setEntity:_entity];
NSError *error = nil;
_modelsArray = [[self managedObjectContext] executeFetchRequest:_fetchRequest error:&error];
if (![[self managedObjectContext]save:&error]) {
NSLog(#"An error has occurred: %#", error);
}
[self.inventoryListTable reloadData];
}
- (NSNumber *)loadImagesBySerialNumber: (NSString *)serialNumber
{
_imagesFetchRequest = [[NSFetchRequest alloc]init];
_imagesEntity = [NSEntityDescription entityForName:#"InventoryImage" inManagedObjectContext:[self managedObjectContext]];
_imagesPredicate = [NSPredicate predicateWithFormat:#"serialNumber = %# && group <> 'm-FLP' && imageSource <> 'MDL'", serialNumber];
[_imagesFetchRequest setEntity:_imagesEntity];
[_imagesFetchRequest setPredicate:_imagesPredicate];
NSError *error = nil;
_imagesArray = [[self managedObjectContext] executeFetchRequest:_imagesFetchRequest error:&error];
NSNumber *imageCount = [NSNumber numberWithInteger:[_imagesArray count]];
return imageCount;
}
- (void)loadImages
{
_imagesFetchRequest = [[NSFetchRequest alloc]init];
_imagesEntity = [NSEntityDescription entityForName:#"InventoryImage" inManagedObjectContext:[self managedObjectContext]];
[_imagesFetchRequest setEntity:_imagesEntity];
NSError *error = nil;
_imagesArray = [[self managedObjectContext] executeFetchRequest:_imagesFetchRequest error:&error];
}
/* End Load Inventory and Image From Core Data */
- (void)clearModelEntity:(NSString *)entity
{
_fetchRequest = [[NSFetchRequest alloc]init];
_entity = [NSEntityDescription entityForName:entity inManagedObjectContext:[self managedObjectContext]];
[_fetchRequest setEntity:_entity];
NSError *error = nil;
_modelsArray = [[self managedObjectContext] executeFetchRequest:_fetchRequest error:&error];
for (NSManagedObject *object in _modelsArray) {
[[self managedObjectContext] deleteObject:object];
}
NSError *saveError = nil;
if (![[self managedObjectContext] save:&saveError]) {
NSLog(#"An error has occurred: %#", saveError);
}
}
- (void)clearImageEntity:(NSString *)entity
{
_fetchRequest = [[NSFetchRequest alloc]init];
_entity = [NSEntityDescription entityForName:entity inManagedObjectContext:[self managedObjectContext]];
[_fetchRequest setEntity:_entity];
NSError *error = nil;
_imagesArray = [[self managedObjectContext] executeFetchRequest:_fetchRequest error:&error];
for (NSManagedObject *object in _imagesArray) {
[[self managedObjectContext] deleteObject:object];
}
NSError *saveError = nil;
if (![[self managedObjectContext] save:&saveError]) {
NSLog(#"An error has occurred: %#", saveError);
}
}
Don't forget to call [save:conetext]. if you close without saving you will lost your data.
I am using core data for my application.It works fine on simulator but not retreiving the details on real device.Device is of iOS6.1.This is the code i am using:
- (NSManagedObjectContext *) getCurrentMangedContext
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"ForceData" withExtension:#"momd"];
NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSURL *storeURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]URLByAppendingPathComponent:#"ForceData.sqlite"];
NSError *error = nil;
NSPersistentStoreCoordinator *persistantStroreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
if (![persistantStroreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
{
}
NSManagedObjectContext *managedContext = [[NSManagedObjectContext alloc] init] ;
[managedContext setPersistentStoreCoordinator:persistantStroreCoordinator];
modelURL = nil;
return managedContext;
}
This is how i am saving my login details and it is not giving any error.
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User" inManagedObjectContext:context];
[request setEntity:entity];
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
if (emailString != nil)
{
[newManagedObject setValue:emailString forKey:#"email"];
}
if (genderString != nil)
{
[newManagedObject setValue:genderString forKey:#"gender"];
}
if (fNameString != nil)
{
[newManagedObject setValue:fNameString forKey:#"firstName"];
}
if (lNameString != nil)
{
[newManagedObject setValue:lNameString forKey:#"lastName"];
}
if (userIDString != nil)
{
[newManagedObject setValue:userIDString forKey:#"userID"];
}
NSError *error = nil;
if (![context save:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
// Insert User details to the user DB <--------------------------
And this is how i am retrieving:
- (User *) getActiveUser
{
NSManagedObjectContext *context = [self getCurrentMangedContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"User" inManagedObjectContext:context];
[request setEntity:entity];
NSError *errorFetch = nil;
NSArray *array = [context executeFetchRequest:request error:&errorFetch];
User *objUser = (User *) [array lastObject];
NSLog(#"%#",objUser);
return objUser;
}
But i am not getting the user details on device but getting on simulator.anyone faced this same?
In your case I'd suggest that ARC releases your managedObjectContext after executing the fetch request.
Make sure that you hold a strong reference to the appropriate managedObjectContext during the whole lifetime of your managedObject somewhere in your app (e.g. your ApplicationDelegate). A NSManagedObject can't live without it's managedObjectContext. The Core Data project template shows how to do that.
Further information about ARC and strong references: https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
I'm currently having a threading issue with the managedObjectContext within my application. Currently, I have a background thread running that MUST be in the background, but accesses the managedObjectContext at the same time. Another ViewController calls on the method processAllApplications shown below that then calls checkCompletedApplicationsFor24HourExpiration which then calls getAppsWithStatus. The thread seems to be currently locked causing this operation to halt where the warning below is. I need a way to process this through and am quite a noob when it comes to Core Data. Would anyone be able to advise. I was reading that I may have to create multiple instances of my managedObject and merge them. How would I go about that if that is the case?
AppDelegate:
- (NSManagedObjectContext *)managedObjectContext
{
[__managedObjectContext lock];
if (__managedObjectContext != nil) {
[__managedObjectContext unlock];
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
[__managedObjectContext unlock];
return __managedObjectContext;
}
- (NSMutableArray*)getAppsWithStatus:(int)intStatus {
NSLog(#"%i on main thread getAppsWithStatus", [NSThread currentThread].isMainThread);
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Application" inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *status = [NSNumber numberWithInt:intStatus];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"status = %# && username = %#", status, [[NSUserDefaults standardUserDefaults] objectForKey:#"username"]];
#warning FAILS HERE INTO ABYSS
[request setPredicate:predicate];
NSError *error = nil;
NSMutableArray* applications = [[NSMutableArray alloc] initWithArray:[self.managedObjectContext executeFetchRequest:request error:&error]];
for (Application* eachApp in applications)
eachApp.applicationNumber = nil;
[self saveDB];
return applications;
}
- (void)processAllApplications:(id)userInfo {
[self.processApplicationsLock lock];
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"username"] == nil) return; // Not logged in
NSLog(#"processing");
[self checkCompletedApplicationsFor24HourExpiration];
[self alertFor12HourCompletedApplications];
[self alertForExpiredDraftApplications];
if ([DeleteAllDraftApplicationsForCurrentApplicationYear isSatisifiedByDate:[DateTimeFactory currentApplicationDate]]) {
[self deleteExpiredApps];
}
[self performSelector:#selector(sendApplications:) withObject:nil afterDelay:3];
[self.processApplicationsLock unlock];
}
- (void)checkCompletedApplicationsFor24HourExpiration {
NSLog(#"OutboxSender - (void)checkCompletedApplicationsFor24HourExpiration");
NSLog(#"%i on main thread checkCompletedApplicationsFor24HourExpiration", [NSThread currentThread].isMainThread);
NSArray* completedApps = [self getAppsWithStatus:STATUS_COMPLETED];
NSDate* targetDate = [self offsetDate:[DateTimeFactory currentApplicationDate] withDay:-1 withMonth:0 withHour:0];
for (Application* theApplication in completedApps) {
if ([MoveCompletedApplicationToDraftApplicationSpec isSatisfiedByApplication:theApplication cutOffDate:targetDate]) {
NSLog(#"Sending To draft with date: %#", theApplication.submittedDate);
theApplication.status = [NSNumber numberWithInt:STATUS_DRAFT];
[self deleteSignatures:theApplication];
}
}
NSString* message = [NSString stringWithFormat:#"%i completed application/s have been sent to drafts", [completedApps count]];
echo_Alert(#"", message);
[self saveDB];
}
create separate managed object context
+(NSManagedObjectContext *)getManagedObjectContext
{
NSManagedObjectContext *managedObjectContext;
#try {
NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
}
#catch (NSException *exception) {
NSLog(#"Exception occur %#",exception);
}
return managedObjectContext;
Use this separate managed object context in your fetching method,
- (NSMutableArray*)getAppsWithStatus:(int)intStatus {
NSMutableArray * mutableObjects;
NSLog(#"%i on main thread getAppsWithStatus", [NSThread currentThread].isMainThread);
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Application" inManagedObjectContext:[self getManagedObjectContext]]; // Here use separate managed object context
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *status = [NSNumber numberWithInt:intStatus];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"status = %# && username = %#", status, [[NSUserDefaults standardUserDefaults] objectForKey:#"username"]];
#warning FAILS HERE INTO ABYSS
[request setPredicate:predicate];
NSError *error = nil;
NSMutableArray* applications = [[NSMutableArray alloc] initWithArray:[[self getManagedObjectContext] executeFetchRequest:request error:&error]];
NSMutableArray * resultedArray = [applications mutableCopy];
NSMutableArray * objectIds = [[NSMutableArray alloc] initWithCapacity:[resultedArray count]];
for (NSManagedObject *obj in resultedArray) {
[objectIds addObject:obj.objectID];
}
mutableObjects = [[NSMutableArray alloc] initWithCapacity:[objectIds count]];
for (NSManagedObjectID * objectID in objectIds) {
NSManagedObject * obj = [self.managedObjectContext
objectWithID:objectID]; // Here use self.managedObjectContext in which you already created.
[mutableObjects addObject:obj];
}
for (Application* eachApp in mutableObjects)
eachApp.applicationNumber = nil;
[self saveDB];
return mutableObjects;
}