Can't pass NSManagedObjectContext to TableViewClass - objective-c

I've got the problem to pass my managedobjectcontext to my tableviewcontroller. It doesn't with UserDefaults or with Notification. My storyboard is too big to pass it from my RootViewController:
AppDelegate:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
Schulung *first = [NSEntityDescription insertNewObjectForEntityForName:#"Schulung" inManagedObjectContext:self.managedObjectContext];
first.name=#"testname";
first.info=#"testinfo";
first.location=#"testlocation";
Abhaltungsdatum *firstDate = [NSEntityDescription insertNewObjectForEntityForName:#"Abhaltungsdatum" inManagedObjectContext:self.managedObjectContext];
firstDate.datum = [NSDate date];
firstDate.schulung=first;
Abhaltungsdatum *secondDate = [NSEntityDescription insertNewObjectForEntityForName:#"Abhaltungsdatum" inManagedObjectContext:self.managedObjectContext];
secondDate.datum=[NSDate date];
secondDate.schulung=first;
NSLog(#"Entities: %#",[[self.managedObjectContext.persistentStoreCoordinator.managedObjectModel entities]valueForKey:#"name"]);
// NSUserDefaults *theDefaults = [NSUserDefaults standardUserDefaults];
// NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.managedObjectContext];
// [theDefaults setObject:data forKey:#"managedObjectContext"];
// [theDefaults synchronize];
NSNotificationCenter *theCenter = [NSNotificationCenter defaultCenter];
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:self.managedObjectContext forKey:#"context"];
[theCenter postNotificationName:#"managedObjectContext" object:nil userInfo:dictionary];
return YES;
}
myTableViewController:
-(void)viewDidLoad
{
[super viewDidLoad];
NSNotificationCenter *theCenter = [NSNotificationCenter defaultCenter];
[theCenter addObserver:self selector:#selector(addManagedObjectContext:) name:#"managedObjectContext" object:nil];
// NSUserDefaults *theDefaults = [NSUserDefaults standardUserDefaults];
// NSData *data = [theDefaults objectForKey:#"managedObjectContext"];
// self.managedObjectContext = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// [theDefaults synchronize];
NSLog(#"Entities: %#",[[self.managedObjectContext.persistentStoreCoordinator.managedObjectModel entities]valueForKey:#"name"]);
NSFetchRequest *theRequest = self.fetchRequest;
NSFetchedResultsController *theController = [[NSFetchedResultsController alloc] initWithFetchRequest:theRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
NSError *theError = nil;
theController.delegate = self;
if([theController performFetch:&theError]) {
self.fetchedResultsController = theController;
}
else {
NSLog(#"viewDidLoad: %#", theError);
}
}
-(void)addManagedObjectContext:(NSNotification *)note{
self.managedObjectContext = [[note userInfo]valueForKey:#"context"];
}
The NSUserDefault Object gets nil when passed and the Notification doesn't come through.

Related

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

NSManagedObjectContext crashing when accessed on external thread

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

Failed to load UIDocuments in separate devices

I have created a UIDocument to wrap a custom object. The UIDocument is successfully saving to iCloud, and I am successfully loading each UIDocument when I run the app each time. However, when I attempt to run the app on a new device (iPhone 5) it will not load any UIDocument from iCloud, but I can check iCloud under Settings and see the files that are saved under my app. Does anyone have some steps to check to see why one device (iPhone 4) can load and the other (iPhone 5) cannot? I also cannot create a new UIDocument from the iPhone 5 device.
EDIT
- (void)loadObjects
{
if (!self.objects)
{
self.objects = [[NSMutableArray alloc] init];
}
NSURL *baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (baseURL)
{
self.query = [[NSMetadataQuery alloc] init];
[self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like 'Object_*'", NSMetadataItemFSNameKey];
[self.query setPredicate:predicate];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(queryDidFinish:) name:NSMetadataQueryDidFinishGatheringNotification object:self.query];
[nc addObserver:self selector:#selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:self.query];
[self.query startQuery];
}
}
- (void)queryDidFinish:(NSNotification *)notification
{
[self processQueryResults:notification.object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:notification.object];
self.query = nil;
}
- (void)queryDidUpdate:(NSNotification *)notification
{
[self processQueryResults:notification.object];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:notification.object];
self.query = nil;
}
- (void)processQueryResults:(NSMetadataQuery *)query
{
[query disableUpdates];
[query stopQuery];
[self.objects removeAllObjects];
[query.results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSURL *documentURL = [(NSMetadataItem *)obj valueForAttribute:NSMetadataItemURLKey];
ObjectDocument *document = [[ObjectDocument alloc] initWithFileURL:documentURL];
[document openWithCompletionHandler:^(BOOL success) {
if (success) {
[self.objects addObject:document];
[self sortObjects];
[self.tableView reloadData];
}
}];
}];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)save:(Object *)object
{
NSURL *baseURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (baseURL)
{
NSURL *documentsURL = [baseURL URLByAppendingPathComponent:#"Documents"];
NSURL *documentURL = [documentsURL URLByAppendingPathComponent:[NSString stringWithFormat:#"Object_%f", [object.date timeIntervalSince1970]]];
TVBFlightDocument *document = [[ObjectDocument alloc] initWithFileURL:documentURL];
document.object = object;
[document saveToURL:documentURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Save succeeded.");
[_objects addObject:document];
[self sortObjects];
} else {
NSLog(#"Save failed.");
}
}];
}
}
The app on the iPhone 5 will not load the objects stored in iCloud, but iPhone 4 will load the objects from the iCloud documents.

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

NSNotificationCenter notifications not sent/received

// Question was answered, basicly I should sleep more / code less :)
When my app starts i first load a splash screen, this splashscreen will start a dataDownload when the screen itself is done loading:
Splash.m
#implementation Splash
- (id) init
{
self = [super init];
_lblFunds = [[UILabel alloc] initWithFrame:CGRectMake(350, 330, 324,28)];
_lblFunds.numberOfLines = 1;
[_lblFunds setFont:[UIFont systemFontOfSize:24.0]];
[_lblFunds setTextAlignment: UITextAlignmentCenter];
[_lblFunds setText:#".. Fondsen .."];
[self.view addSubview:_lblFunds];
_lblObjects = [[UILabel alloc] initWithFrame:CGRectMake(350, 360, 324,28)];
_lblObjects.numberOfLines = 1;
[_lblObjects setFont:[UIFont systemFontOfSize:24.0]];
[_lblObjects setTextAlignment: UITextAlignmentCenter];
[_lblObjects setText:#".. Vastgoed Objecten .."];
[self.view addSubview:_lblObjects];
_lblCustomers = [[UILabel alloc] initWithFrame:CGRectMake(350, 390, 324,28)];
_lblCustomers.numberOfLines = 1;
[_lblCustomers setFont:[UIFont systemFontOfSize:24.0]];
[_lblCustomers setTextAlignment: UITextAlignmentCenter];
[_lblCustomers setText:#".. Clienten .."];
[self.view addSubview:_lblCustomers];
return self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(fundsLoaded) name:#"FundsDone" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(customersLoaded) name:#"CustomersDone" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(objectsLoaded) name:#"ObjectsDone" object:nil];
}
- (void) fundsLoaded
{
[_lblFunds setText:[NSString stringWithFormat:#"Fondsen geladen: %d",[[DataManager sharedInstance] fundsCount]]];
}
- (void) objectsLoaded
{
[_lblObjects setText:[NSString stringWithFormat:#"Vastgoed Objecten geladen: %d",[[DataManager sharedInstance] objectsCount]]];
}
- (void) customersLoaded
{
[_lblCustomers setText:[NSString stringWithFormat:#"Clienten geladen: %d",[[DataManager sharedInstance] customersCount]]];
}
- (void) viewDidLoad
{
[super viewDidLoad];
[[DataManager sharedInstance] getData];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
The DataManager will then proceed to use its instance of DataLoader to load and parse the data in a seperate thread, whenever data is parsed and stored away a Notification is sent from the DataLoader. If worked with the Notifications a lot before but this time it just will not work and I cannot seem to figure out why not. There is no error or anything, but the functions as set in the observers are never called. Any ideas on what is wrong are very much welcome, I have read quite a few threads on here, and other sites but haven't found my answer yet.
DataManager.m
#implementation DataManager
static DataManager* _dataManager = nil;
static DataLoader *_dataLoader = nil;
static bool _dataLoaded = FALSE;
- (int) fundsCount
{
return _dataLoader.funds_count;
}
- (int) objectsCount
{
return _dataLoader.objects_count;
}
- (int) customersCount
{
return _dataLoader.customers_count;
}
+ (DataManager *) sharedInstance{
#synchronized([DataManager class])
{
if(!_dataManager)
{
_dataManager = [[super alloc] init];
_dataLoader = [[DataLoader alloc] init];
}
return _dataManager;
}
return nil;
}
- (void) loadDataSucces
{
_dataLoaded = TRUE;
}
- (void) _getData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if(_dataLoader)
{
[_dataLoader loadData];
} else
{
NSLog(#"DataLoader not initialized");
}
[pool drain];
}
- (void) getData
{
[NSThread detachNewThreadSelector:#selector(_getData) toTarget:self withObject:nil];
}
#end
DataLoader.m
- (void) parseData: (NSString *) jsonString
{
NSError *err;
SBJsonParser *parser = [[SBJsonParser alloc] init];
id object = [parser objectWithString:jsonString error:&err];
[jsonString release];
if (!object) {
} else {
//funds
id funds = [object objectForKey:#"fondsen"];
[self deleteAllEntitiesOfType:#"Fund"];
int nr = 0;
for (NSDictionary *i in funds)
{
NSString *naam = [i objectForKey:#"naam"];
if([naam length] > 2)
{
NSManagedObjectContext *context = [(CatalogusAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Fund *f = [NSEntityDescription insertNewObjectForEntityForName:#"Fund" inManagedObjectContext: context];
NSString *integertje = [i objectForKey:#"oid"];
int in = [integertje integerValue];
[f setOid: [NSNumber numberWithInt: in ]];
[f setNaam: naam];
NSError *error = nil;
if( ![context save: &error ])
{
NSLog(#"Error: %#", [[error userInfo] valueForKey:#"ErrorString"]);
} else
{
nr++;
}
}
}
funds_count = nr;
[[NSNotificationCenter defaultCenter] postNotificationName:#"FundsDone" object:nil];
//objects
if( true )
{
id objects = [object objectForKey:#"vastgoedobjecten"];
[self deleteAllEntitiesOfType:#"Object"];
nr = 0;
NSManagedObjectContext *context = [(CatalogusAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
for (NSDictionary *i in objects)
{
Object *o = [NSEntityDescription insertNewObjectForEntityForName:#"Object" inManagedObjectContext: context];
[o setFondsOid:[NSNumber numberWithInt: [ [i objectForKey:#"fondsOid"] integerValue] ]];
[o setOid: [NSNumber numberWithInt: [ [i objectForKey:#"oid"] integerValue] ]];
[o setAdres:[i objectForKey:#"adres"]];
[o setPostcode:[i objectForKey:#"postcode"]];
[o setPlaats: [ i objectForKey:#"plaats"]];
[o setProvincie:[i objectForKey:#"provincie"]];
[o setStatus:[i objectForKey:#"status"]];
[o setSegment:[i objectForKey:#"segment"]];
[o setOppervlakte:[NSNumber numberWithInt: [ [i objectForKey:#"oppervlakte"] integerValue] ]];
[o setBelangrijksteHuurder:[i objectForKey:#"belangrijksteHuurder"]];
[o setWeging:[i objectForKey:#"weging"]];
[o setLongitude:[NSNumber numberWithDouble: [ [i objectForKey:#"longitude"] doubleValue] ]];
[o setLatitude:[NSNumber numberWithDouble: [ [i objectForKey:#"latitude"] doubleValue] ]];
NSError *error = nil;
if( ![context save: &error ])
{
NSLog(#"Error: %#", [[error userInfo] valueForKey:#"ErrorString"]);
} else
{
nr++;
}
}
objects_count = nr;
NSLog(#"ObjectsLoaded");
[[NSNotificationCenter defaultCenter] postNotificationName:#"ObjectsDone" object:nil];
}
//customers
if( true )
{
id custs = [object objectForKey:#"klanten"];
[self deleteAllEntitiesOfType:#"Customer"];
nr = 0;
NSManagedObjectContext *context = [(CatalogusAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
for (NSDictionary *i in custs)
{
Customer *c = [NSEntityDescription insertNewObjectForEntityForName:#"Customer" inManagedObjectContext: context];
[c setOid: [NSNumber numberWithInt: [ [i objectForKey:#"oid"] integerValue] ]];
[c setFondsOid:[NSNumber numberWithInt: [ [i objectForKey:#"fondsOid"] integerValue] ]];
[c setNaam: [i objectForKey:#"naam"]];
NSError *error = nil;
if( ![context save: &error ])
{
NSLog(#"Error: %#", [[error userInfo] valueForKey:#"ErrorString"]);
} else
{
nr++;
}
}
customers_count = nr;
[[NSNotificationCenter defaultCenter] postNotificationName:#"CustomersDone" object:nil];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"DataReady" object:nil];
}
- (void) loadData{
NSString *urlString = #"URL";
NSDate *startDownload = [NSDate date];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *dataFeed = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
if(error){
NSString *d = [ error description ];
NSLog(#"error: %#",d);
} int bytes = [dataFeed length];
NSDate *endDownload = [NSDate date];
NSString *data = [[NSString alloc] initWithData:[NSData decompress:dataFeed] encoding:NSStringEncodingConversionExternalRepresentation];
int string = [data length];
NSDate *endDecompress = [NSDate date];
NSLog(#"Download data: %f - Decompress: %f - BytesDownloaded: %d", [endDownload timeIntervalSinceDate:startDownload], [endDecompress timeIntervalSinceDate:endDownload], bytes);
[[NSNotificationCenter defaultCenter] postNotificationName:#"DownloadDone" object:nil];
[self parseData:data];
}
In init, you should put your registration code BEFORE the return statement. Otherwise it will never run.
Cheers!