NSNotificationCenter notifications not sent/received - objective-c

// 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!

Related

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.

Using Background Fetching with Core Data

I am going through the "iOS 7 Programming Cookbook" and I can't seem to run the script based on the title of my question. Basically, I am trying to create some records in the background queue and then get the results in the main queue but nothing gets passed to the console when I run the code. Here are the methods used in the example. What am I missing here?
- (void) populateDatabase{
for (NSUInteger counter = 0; counter < 1000; counter++){
Person *person =
[NSEntityDescription
insertNewObjectForEntityForName:NSStringFromClass([Person class])
inManagedObjectContext:self.managedObjectContext];
person.firstName = [NSString stringWithFormat:#"First name %lu",
(unsigned long)counter];
person.lastName = [NSString stringWithFormat:#"Last name %lu",
(unsigned long)counter];
person.age = #(counter);
}
NSError *error = nil;
if ([self.managedObjectContext save:&error]){
NSLog(#"Managed to populate the database.");
} else {
NSLog(#"Failed to populate the database. Error = %#", error);
}
}
- (void) processPersons:(NSArray *)paramPersons{
for (Person *person in paramPersons){
NSLog(#"First name = %#, last name = %#, age = %ld",
person.firstName,
person.lastName,
(long)person.age.integerValue);
}
}
- (NSFetchRequest *) newFetchRequest{
NSFetchRequest *request = [[NSFetchRequest alloc]
initWithEntityName:
NSStringFromClass([Person class])];
request.fetchBatchSize = 20;
request.predicate =
[NSPredicate predicateWithFormat:#"(age >= 100) AND (age <= 200)"];
request.resultType = NSManagedObjectIDResultType;
return request;
}
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
__weak NSManagedObjectContext *mainContext = self.managedObjectContext;
__weak AppDelegate *weakSelf = self;
__block NSMutableArray *mutablePersons = nil;
/* Set up the background context */
NSManagedObjectContext *backgroundContext =
[[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.persistentStoreCoordinator =
self.persistentStoreCoordinator;
/* Issue a block on the background context */
[backgroundContext performBlock:^{
NSError *error = nil;
NSArray *personIds = [backgroundContext
executeFetchRequest:[weakSelf newFetchRequest]
error:&error];
if (personIds != nil && error == nil){
mutablePersons = [[NSMutableArray alloc]
initWithCapacity:personIds.count];
/* Now go on the main context and get the objects on that
context using their IDs */
dispatch_async(dispatch_get_main_queue(), ^{
for (NSManagedObjectID *personId in personIds){
Person *person = (Person *)[mainContext
objectWithID:personId];
[mutablePersons addObject:person];
}
[weakSelf processPersons:mutablePersons];
});
} else {
NSLog(#"Failed to execute the fetch request.");
}
}];
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
ViewController *viewController = [[ViewController alloc] init];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}

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.

facebook sharing from iPhone app

In my iphone app i am accessing my facebook info and sending it to the server. From server facebook sharing should happen
I have created my app in FB and while clicking sync button i am able to go to the FB login page.After loged in it asks for the authentication
But it just asking for "basic info" not for public sharing etc (i have included that in my FB app)
-(IBAction)fbConnect:(id)sender{
flag = 1;
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
[self updateView];
} else {
if (appDelegate.session.state != FBSessionStateCreated) {
appDelegate.session = [[FBSession alloc] init];
}
[appDelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
[self updateView];
}];
}
NSLog(#"string issss %#",string);
}
- (void)updateView {
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
string = [NSString stringWithFormat:#"%#",
appDelegate.session.accessToken];
NSLog(#"string issss %#",string);
NSString *urlstrng;
if(flag == 1){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",string];
[self dataFetching:urlstrng];
}
if(flag == 2){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends? access_token=%#",string];
[self dataFetching:urlstrng];
}
} else {
string = [NSString stringWithFormat:#"%#",
appDelegate.session.accessToken];
NSString *urlstrng;
if(flag == 1){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",string];
[self dataFetching:urlstrng];
}
if(flag == 2){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends?access_token=%#",string];
[self dataFetching:urlstrng];
}
}
}
-(void)dataFetching:(NSString*)strng1{
NSURL *url = [NSURL URLWithString:strng1];
ProfileConnector *obj = [[ProfileConnector alloc] init];
obj.delegate1 = self;
[obj parsingJson:url];
}
I believe you are not requesting extra items through your code. You can do it by using openSessionWithAllowLoginUI.
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_location",
#"user_birthday",
#"user_likes",
#"email",
nil];
return [FBSession openActiveSessionWithPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}