I've recently revisited my app which was last built for iOS 8.4 and now updating it to 9.3. It was working fine the first few times I ran it but now crashes on every open, across each simulator with the error: EXC_BAD_ACCESS(code=50)
-(void)beginBackgroundUpdateTask
{
if (self.backgroundTaskAgent == UIBackgroundTaskInvalid)
{
self.backgroundTaskAgent = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
[self endBackgroundUpdateTask];
}];
}
}
-(void)endBackgroundUpdateTask
{
if (self.backgroundTaskAgent != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskAgent];
self.backgroundTaskAgent = UIBackgroundTaskInvalid;
}
}
The crash occurs in the top method with beginBackgroundTaskWithExpirationHandler. I've never had this error before and can't find any solution to it myself or on SO.
Try like this,
-(void)beginBackgroundUpdateTask
{
self.backgroundTaskAgent == UIBackgroundTaskInvalid
self.backgroundTaskAgent = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void) {
[self endBackgroundUpdateTask];
}];
}
-(void)endBackgroundUpdateTask
{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskAgent];
self.backgroundTaskAgent = UIBackgroundTaskInvalid;
}
Related
I want to Disable UI interaction of iPad till the data is downloading on main thread in backend using Blocks
I m downloading the images at loading time
-(void)downLoadImageData{
[self ShowActivityIndicator];
[iOSNetwork getImages:ImageID andEvent:eventID
onCompletion:^(NSString* result,NSError* error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if(error)
{
[self stopFetch:#"Error while Processing"];
}
else
{
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self stopFetch:result];
}
});
}];
}
-(void) stopFetch:(NSString*) result{
[self hideActivityIndicator];
//after downloading completed
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
if use entire application call
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
after downloading completion
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
another choice
[self.view setUserInteractionEnabled:NO];
after the completion
[self.view setUserInteractionEnabled:YES];
one more choice
self.navigationController.navigationBar.userInteractionEnabled=NO;
// perform other events also userInteractionEnabled=NO;
after the completion
self.navigationController.navigationBar.userInteractionEnabled=YES;
// perform other events also userInteractionEnabled=NO;
in your question
-(void)downLoadImageData{
[self ShowActivityIndicator];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents]; // call here
[iOSNetwork getImages:ImageID andEvent:eventID
onCompletion:^(NSString* result,NSError* error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if(error)
{
[self stopFetch:#"Error while Processing"];
}
else
{
[self stopFetch:result];
// not here
}
});
}];
}
You can use MBProgressHud for this. You need to add MBProgressHUD files into project.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.HUD = [[MBProgressHUD alloc] initWithWindow:appDelegate.window];
[appDelegate.window addSubview:self.HUD];
- (void)showHUDWithText:(NSString *)labelText{
if (_isHUDAlreadyInProgress) {
return;
}
_isHUDAlreadyInProgress = TRUE;
[_HUD.superview bringSubviewToFront:_HUD];
self.HUD.labelFont = [UIFont systemFontOfSize:13.0];
//self.HUD.labelText = labelText;
[self.HUD show:TRUE];
}
- (void)hideHUD{
_isHUDAlreadyInProgress = FALSE;
[self.HUD hide:TRUE];
}
Goal is to notify end user about reachability changed when app is in background.
Broadcasting approach NSNotificationCenter not working in background.
second approach i tried beginBackgroundTaskWithExpirationHandler in applicationDidEnterBackground but associated issue with it:
a) Time limitation of 10 min
b) i calling a end loop for detecting the reachability state which run on main thread and in result it choke the UI. Code:-
-(void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"Application entered background state.");
// bgTask is a property of the class
if (isUserLogin) {
NSAssert(self.bgTask == UIBackgroundTaskInvalid, nil);
bgTask = [application beginBackgroundTaskWithExpirationHandler: ^{
dispatch_async(dispatch_get_current_queue(), ^{
[application endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
});
}];
dispatch_async(dispatch_get_current_queue(), ^{
while ([application backgroundTimeRemaining] > 1.0) {
curReach = [[utilities sharedUtility]reachabilityChanged];
NetworkStatus netStatus = [curReach currentReachabilityStatus];
NSLog(#"-----------back ground task------------");
if (netStatus == ReachableViaWWAN || netStatus == ReachableViaWiFi) {
//isNetworkMessagePopup = YES;
}
else{
// if (isNetworkMessagePopup) {
// isNetworkMessagePopup = NO;
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif) {
localNotif.alertBody = FORMAT_UNABLE_TO_CONNECT_SERVER_DUE_TO_NO_INTERNET;
localNotif.alertAction = NSLocalizedString(#"Read Message", nil);
localNotif.soundName = #"pushNotification.caf";
localNotif.repeatInterval = 5;
//localNotif.applicationIconBadgeNumber = 1;
[application presentLocalNotificationNow:localNotif];
[localNotif release];
break;
//}
}
}
}
[application endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
});
}
}
Please suggest me is it possible to notify user in iOS whenever reachability changed and app in background state?
If yes then how can i achieve this.
Thanks.
You could possibly use the background fetch capability as described in the iOS App Programming Guide to check reach ability and post a local notification if the network is un available.
There is no guarantee of how often this will be called - probably in the order of every few minutes or longer - certainly not every few seconds.
I am trying to track's user location when the application moves to background. I just need to track once. So, I am not using background location services. In the code below this works when I uncomment 1 but it doesn't work when I uncomment 2.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// 1 works here [self startStandardUpdates];
self.bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
// 2 doesn't work here [self startStandardUpdates];
});
}
In second case this delegate function is not called.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"Updated\n%#",locations);
[self.manager stopUpdatingLocation];
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}
Can someone tell me why this is not working in 2nd case. Also, is it fine using [self startStandardUpdates] in the first position ?
Try this
By default, this is YES for applications linked against iOS 6.0 or later.
if ([self.manager respondsToSelector:#selector(pausesLocationUpdatesAutomatically)]) {
self.manager.pausesLocationUpdatesAutomatically = NO;
}
I want to fetch service for every 15 mins,so i am using NSTimer.It is working fine.But how to call same service while app is in background state by using nstimer.Nstimer is not working in background state.Please suggest me.
//when the application is about to move from active to inactive state.
- (void)applicationWillResignActive:(UIApplication *)application
{
[self sendBackgroundLocationToServer];
}
- (void) sendBackgroundLocationToServer
{
UIBackgroundTaskIdentifier bgTask = UIBackgroundTaskInvalid;
bgTask = [[UIApplication sharedApplication]
beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}];
//Start Timer
[self startTimer];
//Close the task
if (bgTask != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}
}
-(void) closeUpShopBeforeBackgrounding {
// this listen to the UIApplicationDidEnterBackgroundNotification
[self beginBackgroundUpdateTask];
// do some closing stuff
[self endBackgroundUpdateTask]; }
- (void) beginBackgroundUpdateTask {
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}]; }
- (void) endBackgroundUpdateTask {
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid; }
This code is working fine for me, but when I foreground the app again, its dead in the water. Its as if the viewDidLoads are not firing, and nothing is happening.
Is there anything I need to do when the app foregrounds to kick it back into life?