Background fetch not updating UI - objective-c

I'm new to ios7 background fetch. Here is how I'm doing it.
This is what is going on in appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *url = [[NSURL alloc] initWithString:#"http://sample.com/api/home/lastnews"];
OldJson = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
}
Note that here I'm storing the whole JSON file in a string so i can use to check for new content.
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
//HomepageView is the view controller that is supposed to be updated
HomepageView *homepage = [[HomepageView alloc] init];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURL *url = [[NSURL alloc] initWithString:#"http://sample.com/api/home/lastnews"];
NewJson = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
NSURLSessionDataTask *task = [session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
completionHandler(UIBackgroundFetchResultFailed);
return;
}
if (![NewJson isEqualToString:OldJson])
{
completionHandler(UIBackgroundFetchResultNewData);
NSLog(#"New Data : %#",NewJson);
}
else
{
completionHandler(UIBackgroundFetchResultNoData);
NSLog(#"Old Json : %#",OldJson);
}
}];
// Start the task
[task resume];
}
Now to test the whole process, i simply run the application. Then i send it to background and then when i have new content in the JSON file, i use the Simulate Background Fetch operation from the Debug menu. Then i open the application but nothing has changed.

First store your newJson in NSUserDefaults as seen below
if (![NewJson isEqualToString:OldJson])
{
completionHandler(UIBackgroundFetchResultNewData);
NSLog(#"New Data : %#",NewJson);
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:NewJson forKey:#"newJson"];
}
Second in your View Controller add this in the ViewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(refresh:) name: UIApplicationWillEnterForegroundNotification object:nil];
Add this to your viewWillAppear
-(void)viewWillAppear:(BOOL)animated{
[self loadData];
}
Create the loadData
- (void)loadData {
// contains information the ViewController makes use of
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
textView.text = [defaults objectForKey:#"newJson"];
}
Finally add your action
-(IBAction)refresh:(id) sender {
NSLog(#"I ran");
[self loadData];
}
I tested this and it works.

Three problems:
There's no guarantee that JSON data comes in UTF-8 format. Use [NSData dataWithContensOfURL:...]
Never, ever access a URL from the main thread. If the server doesn't respond, your app will be hanging.
Really bad: In your background fetch handler, you actually load the URL synchronously. And then you create a task to load it again. So you load it actually twice.

Related

Creating video preview on iCarousel using PFFiles from Parse IOS

I have created an iCarousel View and am trying to display a video preview in each "cell"/view.
I have the videos stored in Parse and am trying to
Query from the cloud
Retrieve the data from the PFFile
Convert the data to URL
Play URL using AVPlayer
Here my code so far.
-(void)getPast{
dataArray = [[NSMutableArray alloc]init];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
PFQuery *query = [PFQuery queryWithClassName:#"History"];
[query whereKey:#"Location" containsString:[defaults objectForKey:#"location"]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
pastArray = [NSMutableArray arrayWithArray:objects];
for (PFObject *files in objects){
PFFile *file = [files objectForKey:#"File"];
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
[dataArray addObject:data];
}];
}
[self.carouselView reloadData];
}];
}
Im getting an error saying that my dataArray is empty,
I think the problem here could be that since I'm querying in the background, the For loop is finishing before I have received the data and therefore the array is empty, although I could be wrong and I don't know how to fix this even if I was right.
Code for displaying preview
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view {
PFObject *object = [pastArray objectAtIndex:index];
NSData *data = [dataArray objectAtIndex:index];
NSString *dataString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:dataString];
NSLog(#"URL %#",URL);
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 275)];
self.playerViewController = [[AVPlayerViewController alloc]init];
self.playerViewController.player = [AVPlayer playerWithURL:URL];
self.playerViewController.view.frame = view.bounds;
self.playerViewController.showsPlaybackControls = NO;
[view addSubview:self.playerViewController.view];
view.autoresizesSubviews = YES;
self.playerViewController.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.playerViewController.player.currentItem];
[self.playerViewController.player play];
return view;
}
How can I fix my code so that each view autoplays the PFFile video corresponding to its index in the Array.
My problems:
Array is empty
Playing content for each view isn't working
Ps. Im aware that I'm not using PFObject *object.
As you guessed the for cycle finishes it's execution way before the blocks are called, you have to make sure the data is loaded before you call reloadData
The first thing that comes to my mind on how to handle this will be something like
for (PFObject *files in objects){
PFFile *file = [files objectForKey:#"File"];
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
[dataArray addObject:data];
[self checkData];
}];
}
- (void)checkData {
//Check the if the data is completed
if(dataArray.count == numberOfFiles) { //Maybe a more complex if is required here but you get the idea
//All files are downloaded
dispatch_async(dispatch_get_main_queue(), ^{
//We are sure the data is ready so we reload it
[self.carouselView reloadData];
});
}
}
Also you should always check if NSData is valid before loading it

How to show JSON data in UIView labels

About every single tutorial and example on the internet I see shows how to fetch JSON from some url and show it in Tableview. This is not my problem I know how to do that with AFNetworking framework or with native APIs.
My problem is that after I have downloaded the JSON, I want to show some of it in my UIView labels. I have actually succeeded doing this when I was trying to find a way around NSURLSession inability to cache in iOS 8. But I didn't realize that it was synchronous.
Factory.m
+ (Factory *)responseJson
{
static Factory *shared = nil;
shared = [[Factory alloc] init];
NSHTTPURLResponse *response = nil;
NSString *jsonUrlString = [NSString stringWithFormat:#"http://urltojson.com/file.json"];
NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSError *error = nil;
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:10.0];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error) {
NSLog(#"error");
} else {
//-- JSON Parsing
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
//NSLog(#"Result = %#",result);
shared.responseJson = result;
}
return shared;
}
My question is that is it possible to use for example AFNetwoking to do the same thing? Am I missing some method that I need to call like in case of a TableView
[self.tableView reloadData];
I would like to use that framework because I need to check Reachability and it seems to implement it already.
Edit as asked to show more code
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self factoryLoad];
[self setupView];
}
- (void)factoryLoad
{
Factory *shared = [Factory responseJson];
self.titles = [shared.responseJson valueForKeyPath:#"data.title"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
- (void)setupView
{
self.issueTitleLabel.text = [self.titles objectAtIndex:0];
}
There are a couple oddities in the code you posted.
Factory, which appears to be a singleton class, should be instantiated inside a dispatch_once to ensure thread safety.
In ViewController.m, you are calling factoryLoad on the main thread, which is subsequently calling sendSynchronousRequest on the main thread. Apple's NSURLConnection Documentation warns against calling this function on the main thread as it blocks the thread, making your application unresponsive to user input.
You should not be passing in nil as the error parameter in NSJSONSerialization JSONObjectWithData:.
In your case I would recommend separating the fetching of data from the construction of your singleton object.
Factory.m
+(Factory *)sharedFactory {
static Factory *sharedFactory = nil;
dispatch_once_t onceToken;
dispatch_once(&onceToken, {
sharedFactory = [[Factory alloc] init];
});
}
-(void)fetchDataInBackgroundWithCompletionHandler:(void(^)(NSURLResponse *response,
NSData *data,
NSError *error)
completion {
NSHTTPURLResponse *response = nil;
NSString *jsonUrlString = [NSString stringWithFormat:#"http://urltojson.com/file.json"];
NSURL *url = [NSURL URLWithString:[jsonUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:10.0];
NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request
queue:downloadQueue
completionHandler:completion];
}
Now you should be able to create a reference to the data with a guarantee that the download request has finished and thus the data will exist.
ViewController.m
-(void)factoryLoad {
[[Factory sharedFactory] fetchDataInBackgroundWithCompletionHandler:^(void)(NSURLResponse *response, NSData *data, NSError *error){
if(!error) {
NSError *error2;
NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error2];
if(error2){ /* handle error */ }
self.titles = [serializedData valueForKeyPath:#"data.title"];
[Factory sharedFactory].responseJSON = serializedData;
}
else {
// handle error
}
}];
}
This will guarantee that the download has completed before you try to access any of the downloaded information. However, I've left a few things out here, including any sort of activity indicator displaying to the user that the app is doing something important in the background. The rest is, uh, left as an exercise to the reader.
Ok I took a deeper investigation into Morgan Chen's answer and how to block.
The example code took some modification but I think It works as it should and is better code.
In Factory.m
+ (Factory *) sharedInstance
{
static Factory *_sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
-(void)fetchDataInBackgroundWithCompletionHandler: (void(^)(BOOL success, NSDictionary *data, NSError *error)) block
{
NSString * baseURL = #"http://jsonurl.com/file.json";
AFHTTPRequestOperationManager * manager = [[AFHTTPRequestOperationManager alloc] init];
__weak AFHTTPRequestOperationManager *weakManager = manager;
NSOperationQueue *operationQueue = manager.operationQueue;
[manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(#"internet!");
[weakManager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[operationQueue setSuspended:NO];
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(#"no internet");
[weakManager.requestSerializer setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
[operationQueue setSuspended:YES];
break;
default:
break;
}
}];
[manager.reachabilityManager startMonitoring];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:baseURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (responseObject && [responseObject isKindOfClass:[NSDictionary class]]) {
block(YES, responseObject, nil);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) { // invalid request.
NSLog(#"%#", error.localizedDescription);
block(NO, nil, error);
}];
}
In ViewController.m I call this method on viewDidLoad
-(void)factoryLoad
{
[[Factory sharedInstance] fetchDataInBackgroundWithCompletionHandler:^(BOOL success, NSDictionary *data, NSError *error) {
if (success) {
NSLog(#"we have stuff");
self.responseData = data;
self.titles = [self.responseData valueForKeyPath:#"data.title"];
[self setupView];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
}];
}

how do you refresh ABUnknownPersonViewController?

My problem: I have a ABUnknownPersonViewController which needs to get an image from an online database. I have implemented an NSSession to download the image. The thread adds the image to the ABRecordRef then adds it to the ABUnknownPersonViewController. When the controller is pushed on the stack, it doesn't show the image...therfore sadness ensues.
NSString *imageUrl = dict[#"mug"];
__block NSURL *url = [NSURL URLWithString:imageUrl];
__block NSData *urlData = nil;
NSURLSessionConfiguration *sessionConfig =
[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session =
[NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
NSURLSessionDownloadTask *getImageTask =
[session downloadTaskWithURL:[NSURL URLWithString:imageUrl]
completionHandler:^(NSURL *location,
NSURLResponse *response,
NSError *error) {
urlData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
newPerson = controller.displayedPerson;
ABPersonSetImageData(newPerson, (__bridge CFDataRef)(urlData), &anError);
controller.displayedPerson = newPerson;
if(urlData != nil) {
NSLog(#"I got here");
[self viewWillAppear:YES];
[[NSNotificationCenter defaultCenter] postNotificationName:#"com.razeware.imagegrabber.imageupdated" object:(__bridge id)(newPerson)];
}
});
}];
[getImageTask resume];
**Oddly enough, if I choose "Create New Contact" the image appears (So, the thread is working?). If I click cancel on iPhone then the image appears on the ABUnknownPersonViewController. So, it seems like the controller just needs to be refreshed. How?
I've tried [[self view] setNeedsDisplay]; //ain't working'
Help please!
OK - This may not be the best practice. However, since you already have [self viewWillAppear:YES]; you can try calling [self viewWillDisappear:NO]; before viewWillAppear. This is likely to refresh the content.
Sourced from here.
I had a similar problem recently and got this from somewhere else. Try adding a dispatch sync after the async to the main queue like this:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
dispatch_sync(dispatch_get_main_queue(), ^{
// your image fetch code here
});
});
I found a solution:
ABRecordRef cannot be updated in a thread. It must be updated on the main thread.

NSURLSessionDataTask doesn't update my table

I have a class for get xml and parse it.
+ (instancetype)sharedRssNewsLoader
{
static BGMRssNewsLoader *sharedRssNewsLoader = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedRssNewsLoader = [[self alloc] initPrivate];
});
return sharedRssNewsLoader;
}
- (instancetype)initPrivate
{
self = [super init];
//did the superclass's designated initializer succeed?
if (self)
{
self.rssNewsItems = [[NSMutableArray alloc] init];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
//RSS call
[self fetchFeed];
}
return self;
}
- (void)fetchFeed
{
NSString *requestString = #"http://xxx...";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
self.rssXmlString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
DDLogVerbose(#"rssXmlString: %#", self.rssXmlString);
dispatch_sync(dispatch_get_main_queue(), ^{
[self parseXML:self.rssXmlString];
});}
];
[dataTask resume];
}
//parse XML
- (void)parseXML:(NSString *)source
{
NSError *error = nil;
DDXMLDocument *theDocument = [[DDXMLDocument alloc] initWithXMLString:source
options:0
error:&error];
NSArray *xmlItems = [theDocument nodesForXPath:#"//item"
error:&error];
for(DDXMLElement *itemElement in xmlItems)
{
NSString *itemTitleValue = [[[itemElement elementsForName:#"title"] lastObject] stringValue];
NSString *itemDescriptionValue = [[[itemElement elementsForName:#"title"] lastObject] stringValue];
BGMRssNewsEntry *rssEntry = [[BGMRssNewsEntry alloc] initRssNewsEntryWithTitle:itemTitleValue
rssText:itemDescriptionValue
rssUrl:nil
rssDate:nil
isRssRead:NO];
[self.rssNewsItems addObject:rssEntry];
}
}
//if a programmer calls [[BGMItemsStore alloc] init], let him know the error of his ways
- (instancetype) init
{
#throw [NSException exceptionWithName:#"Singleton"
reason:#"You are wrong! Use +[BBGMRssNewsLoader sharedRssNewsLoader]"
userInfo:nil];
return nil;
}
I would like to show result in the table. So in the other class I do:
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
//custom initialization
//initialization sharedRssNewsLoader with rssItems array and RSS call
[BGMRssNewsLoader sharedRssNewsLoader];
}
return self;
}
But my table is absolutely clear. I know that I need to switch to main_queue when I am working with NSURLSessionDataTask, I did it. I think that I mess with thread :(
That BGMRssNewsLoader is asynchronously loading the data and in parseXML you are adding entries to the self.rssNewsItems object. But I don't see where it tells the table to reload itself when this asynchronous request done. If your table view's data source tries to immediately retrieve the rssNewsItems array, it will likely be empty until the asynchronous request is complete.
Generally, when you're done loading the data, you'd call [self.tableView reloadData] (either by supplying the tableview as a parameter during the instantiation of the BGMRssNewsLoader, or by having it post a notification that the table view controller is observing, or by supplying a completion block parameter in which you'd perform reloadData).
I'd also suggest temporarily adding a breakpoint or log statement where you add objects to the rssNewsItems array, just to make sure that that the XML feed was successfully retrieved and parsed.
For example, I might retire fetch and define a method like so:
- (void)fetchFeedWithCompletionBlock:(void (^)(NSArray *items, NSError *error))completion
{
NSString *requestString = #"http://xxx...";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
self.rssXmlString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
DDLogVerbose(#"rssXmlString: %#", self.rssXmlString);
dispatch_sync(dispatch_get_main_queue(), ^{
[self parseXML:self.rssXmlString];
if (completion) {
completion(self.rssNewsItems, nil);
}
});
}];
[dataTask resume];
}
I would, by the way, not have the initPrivate method initiate the fetch. You want the caller to be able to supply whatever completion block it wants.
I'd then have the tableview's controller do something like:
[[BGMRssNewsLoader sharedRssNewsLoader] fetchFeedWithCompletionBlock:^(NSArray *items, NSError *error) {
// use the items array and/or error
[self.tableView reloadData];
}];
Clearly, the fetchFeedWithCompletionBlock should actually detect errors and call the completion block with the appropriate NSError (so the table view can decide how it wants to present the error ... the singleton shouldn't be doing anything with the UI itself), but hopefully this illustrates the idea of a network object that provides a completion block to allow the caller to specify what it wants to do when the asynchronous request is complete.

Core Data table getting wiped out when implementing background fetch for app icon badge in iOS7

I am trying to implement a background fetch in my AppDelegate.m to get the app icon badge to reflect an updated record count by pulling the latest record count from a web service via RestKit (not shown here). When I simulate a BackGroundFetch in Xcode everything works fine. When the background fetch runs on my iPhone 5S, my entire table "TicketList" gets wiped out with no data. Here is the code. Has anyone experienced anything similar and can anyone offer some advice as to what i am doing wrong? I've taken out the ReskKit lookup to simplify the code and debug to see if it would have any affect. I've looked at other postings and haven't been able to find an answer as to why this is happening.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//Added this code for the app icon badge functionality
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
return YES;
}
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^) (UIBackgroundFetchResult))completionHandler
{
[UIApplication sharedApplication].applicationIconBadgeNumber = 1;
completionHandler(UIBackgroundFetchResultNewData);
}
*/
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
intAvailCount = 0;
[self setUpCoreDataStack];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"TicketList" inManagedObjectContext:context];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:entity];
self.ticketListData = [[context executeFetchRequest:fetchRequest error:&error] mutableCopy];
if ([ticketListData count] != 0){
//Perform loop through TicketList SQLite DB and count using intAvailCount
TicketList *info = [ticketListData objectAtIndex:0];
for (info in ticketListData) {
//Check to see if tickets in table have been added to do
intAvailCount++;
}
//End Loop
}
[UIApplication sharedApplication].applicationIconBadgeNumber = intAvailCount;
completionHandler(UIBackgroundFetchResultNewData);
}
-(void)setUpCoreDataStack
{
NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:[NSBundle allBundles]];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSURL *url = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:#"TicketList.sqlite"];
NSDictionary *options = #{NSPersistentStoreFileProtectionKey: NSFileProtectionComplete,
NSMigratePersistentStoresAutomaticallyOption:#YES};
NSError *error = nil;
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error];
if (!store)
{
NSLog(#"Error adding persistent store. Error %#",error);
NSError *deleteError = nil;
if ([[NSFileManager defaultManager] removeItemAtURL:url error:&deleteError])
{
error = nil;
store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:options error:&error];
}
if (!store)
{
// Also inform the user...
NSLog(#"Failed to create persistent store. Error %#. Delete error %#",error,deleteError);
abort();
}
}
self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.managedObjectContext.persistentStoreCoordinator = psc;
}
Problem solved. I moved the call to setUpCoreDataStack to the 1st method in my example (didFinishLaunchingWithOptions) which gets called on app startup and my problem was solved. Not exactly sure why this was happening in the 1st place but, i think it had something to do with my setUpCoreDataStack being called every time the perform background fetch method got triggered.