Objective-C, iOS, Core Data, Table Cells empty - objective-c

I've been trying to get through this for a couple of hours now and trying to figure out what is wrong with this code. I'm using core data to save title and a subtitle in a table cell.
I have some setups in my app delegate(sharedAppDelegate) and in my tableview is were I try to inset data into my cells.
Here is what I have in My appDelegate.m:
+(StaticTableAppDelegate *)sharedAppDelegate
{
return sharedInstance;
}
-(NSArray *)allConsoles
{
NSManagedObjectContext *moc = [[StaticTableAppDelegate sharedAppDelegate] managedObjectContext];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Homework" inManagedObjectContext:moc];
[fetch setEntity:entity];
//sort
NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:#"title" ascending:YES];
NSArray *sortdescriptors = [NSArray arrayWithObject:sd];
[fetch setSortDescriptors:sortdescriptors];
NSError *error;
NSArray *result = [moc executeFetchRequest:fetch error:&error];
if(!result){
NSLog(#"%#", [error localizedDescription]);
return nil;
}
return result;
}
And in the view I have this(I imported app delegate):
- (void)viewDidLoad
{
[super viewDidLoad];
NSManagedObjectContext *cxt = [[StaticTableAppDelegate sharedAppDelegate] managedObjectContext];
NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Homework" inManagedObjectContext:cxt];
[request setEntity:entity];
NSArray *arry = [cxt executeFetchRequest:request error:&error];
for( UserData *user in arry){
NSLog(#"title %#", user.title);
NSLog(#"details %#", user.details);
}
StaticTableAppDelegate *ad = [StaticTableAppDelegate sharedAppDelegate];
NSArray *list = [ad allConsoles];
if ([list count]==0) {
tabledata = [[NSMutableArray alloc] init];
tablesubtitles = [[NSMutableArray alloc]init];
[tabledata addObject:#"hello2"];
[tabledata addObject:#"hello2"];
[tabledata addObject:#"hello2"];
[tabledata addObject:#"hello2"];
[tablesubtitles addObject:#"details"];
[tablesubtitles addObject:#"details"];
[tablesubtitles addObject:#"details"];
[tablesubtitles addObject:#"details"];
NSManagedObjectContext *moc = [ad managedObjectContext];
for (int i=0; i<[tabledata count]; i++) {
NSManagedObject *newTabledata = [NSEntityDescription insertNewObjectForEntityForName:#"Homework" inManagedObjectContext:moc];
[newTabledata setValue:[NSString stringWithFormat:[tabledata objectAtIndex:i]] forKey:#"title"];
NSManagedObject *newTablesub = [NSEntityDescription insertNewObjectForEntityForName:#"Homework" inManagedObjectContext:moc];
[newTablesub setValue:[NSString stringWithFormat:[tablesubtitles objectAtIndex:i]] forKey:#"details"];
}
list = [ad allConsoles];
}
tabledata = [tabledata mutableCopy];
}
And tableview method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"homeworkcell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"homeworkcell"];
}
cell.textLabel.text=[[tabledata objectAtIndex:indexPath.row] valueForKey:#"title"];
cell.detailTextLabel.text = [[tablesubtitles objectAtIndex:indexPath.row] valueForKey:#"details"];
cell.textLabel.font = [UIFont systemFontOfSize:14.0];
cell.textLabel.backgroundColor = [ UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
//-----------------------------------------START----------------------------Set image of cell----
cellImage = [UIImage imageNamed:#"checkboxblank.png"];
cell.imageView.image = cellImage;
//--------------------------------------------END---------------------------end set image of cell--
return cell;
}
I appreciate the help.

This is how to store into coreData....If u can change it for your code..
MortgageAppAppDelegate *MortDataObj=(MortgageAppAppDelegate *)[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [MortDataObj managedObjectContext];
loanDetails=[NSEntityDescription
insertNewObjectForEntityForName:#"LoanDetails"
inManagedObjectContext:context];
loanDetails.loanName = name;
loanDetails.loanDescription = desc;
NSError *error;
if (![context save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}

Related

Unit testing with core data in objective c

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;

Check Api Version from web server for update core data

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.
}

Fetch Object with relationship with NSFetchedResultsController

Here's my problem:
I've got 2 Entities :
Session (Date date, String name, NSSet behaviours)
Behaviour (String category, String Time, String name, NSManagedobject session).
They are in a one-to-many relationship.
In SessioneViewController, I fetch the Session and the Behaviours:
// This is for the fetch request
#property (nonatomic, ratain) NSArray *sessionArray;
// Here I create the Session Object
Session *newSession = [NSEntityDescription insertNewObjectForEntityForName:#"Session" inManagedObjectContext:self.managedObjectContext];
newSession.name = self.lblName.text;
newSession.date = [NSDate date];
self.managedObjectContext save:nil];
// I add the Session into the Array
self.sessionsArray = [self.sessionsArray arrayByAddingObject:newSession];
// Here I create the Behaviour Object:
Comportamento *newBehaviour = [NSEntityDescription insertNewObjectForEntityForName:#"Behaviour" inManagedObjectContext:self.managedObjectContext];
newBehaviour.name = cell.textLabel.text;
newBehaviour.category = #"Relationship";
newBehaviour.time = _lblTimer.text;
// Here I say which Session is part of the Behaviour
// --- EDIT ---
// Error Code: newBehaviour.session = [self.sessionsArray objectAtIndex:indexPath.row];
newBehaviour.session = [self.sessionsArray lastObject];
Then I have two view controller classes in which I want to display the Sessions and then when a Session is selected I want the related Behaviours.
// In "ArchiveSessionVC.h":
#property (nonatomic, strong) NSFetchedResultsController *frs;
// In "ArchiveSessionVC.m":
- (void) viwDidLoad
{
if(![[self frs] performFetch:&e]) {
NSLog(#"Error %#", e);
abort();
}
-(NSFetchedResultsController *)frs {
if (_frs != nil) {
return _frs;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Session" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date"
ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
_frs = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
return _fetchedResultControllerSessions;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SessioneCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Sessione *sessione = [self.fetchedResultControllerSessions objectAtIndexPath:indexPath];
cell.textLabel.text = sessione.nome;
return cell;
}
Here is where I push the Second view controller for display the Behaviuors:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Push del ViewController dei comportamenti:
ArchiveBehaviuorsVC *aBehavioursVC = [[ArchiveBehaviuorsVC alloc] initWithNibName:#"ArchiveBehaviuorsVC" bundle:nil];
aBehavioursVC.sessioneSelezionata = [self.fetchedResultControllerSessions objectAtIndexPath:indexPath];
[self.navigationController pushViewController:aBehavioursVC animated:YES];
}
My ArchiveBehaviuorsVC is like this:
//"ArchiveBehaviuorsVC.h"
#property (nonatomic, strong) Session *selectedSession;
-(NSFetchedResultsController *)fetchedResultControllerBehaviours
{
if (_fetchedResultControllerBehaviours != nil) {
return _fetchedResultControllerBehaviours;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Behaviour" inManagedObjectContext:self.managedObjectContext];
//NSPredicate *predicate = [NSPredicate predicateWithFormat:#"session == %#",self.sessioneSelezionata];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"nome"
ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
_fetchedResultControllerBehaviours = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
return _fetchedResultControllerBehaviours;
}
This is part of the code but it doesn't work. How do I tell the fetchedResultzController to display only the Behaviours associate with the Session?
-- EDIT ---
I found the problem, it wasn't a NSPredicate error, the problem was in this line of code:
// Error Code: newBehaviour.session = [self.sessionsArray objectAtIndex:indexPath.row];
// Right Code:
newBehaviour.session = [self.sessionsArray lastObject];
The predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"session == %#",self.sessioneSelezionata];
looks ok to me.
Are you sure you are obtaining the wrong behavior? Did you try to enable SQL debugging?
-com.apple.CoreData.SQLDebug X
where X can be 1,2 or 3. The higher the value the more SQL output.
In addition, when you do a save ALWAYS pass in an error reference.
NSError* error = nil;
[context save:&error];
The above snippet returns a bool value so check it. If NO is returned print the error.

Some data not staying in Core Data

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.

Table using NSFetchedResultsController starts empty when using iCloud

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