App restarts if re-opened from app switcher - ios

I have an app that is being restarted after being in the background for 10 minutes and then re-opened from the app switcher. I have a page (3rd page) that contains a textview, upon editing it. I pressed the home button and locked for 12 minutes, when I went back to the app via app switcher, the app restarts (goes back to the 1st page or is relaunched).
Is there a way to prevent this?
EDIT:
Turns out the my code on the applicationDidEnterBackground:
_bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:_bgTask];
}];
is causing the termination of my app in the background. any advice please?

Related

iOS app appears to still be in background after calling exit()

I am trying to smoothly close down my app.
First I put the app in the background and tried to use exit(0) to close down the app:
//home button press programmatically
UIApplication *app = [UIApplication sharedApplication];
[app performSelector:#selector(suspend)];
//wait 2 seconds while app is going background
[NSThread sleepForTimeInterval:2.0];
//exit app when app is in background
exit(0);
My problem is, when I check to see what apps are running in the background, the app is still there. I thought exit(0) would remove it from the background.
It appears my app is going under recently used. Is there a way to programmatically remove it from that list?
You can't programmatically remove an app from the "recently used apps" list. When a user double-taps the Home button, the list of recently used apps is just that - a list of recently used app. It has absolutely nothing at all to with whether the app is fully terminated or suspended in the background.
Calling exit(0); simply terminates your app. But it was still recently used so it appears in the list when the user double-taps the Home button.
In XCode edit the info.plist adding the setting "Application does not run in background" with a value of YES to make your application exit every time:
Setting this will add UIApplicationExitsOnSuspend to info.plist:
<key>UIApplicationExitsOnSuspend</key>
<true/>

App background - foreground states

Is there a way i could stop an app from going into background ? Or is there a way in which i could bring my app to foreground if it did go into background ?
I'm making a showcase app for a client and the app must always run on the iPad without interaction from the user.
You can force your app to stay active using following code
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
But if you press home button of device, the app will go in background. You cannot force to stop this.
In this case you can use UILocalNotification to bring the app to the foreground if the device is locked, a notification appears, and the user unlocks the device or if user tap on the notification.
You can also fire a local notification whenever user going to background in
applicationDidEnterBackground: method

Detecting when app is becoming active from lockscreen vs other on iOS7

My app has different behavior when becoming active from the lockscreen (locked while active), or becoming active from anything else.
On iOS 6 and lower I could detect this
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (UIApplicationStateInactive == state)
// Coming from locked screen (iOS 6)
else
// Coming from Springboard, another app, etc...
But on iOS 7, the state value is UIApplicationStateBackground in both scenarios. Is this the intended behavior? How can I properly detect whether the app is launching from the lockscreen now?
Registered devs, I already posted this on the devforums before the NDA was lifted, see here
I was able to figure out a hack on this and so far seems to be reliable. It only works on the device, not the simulator, and has been tested on an iPhone 5s, 5 and 4S running iOS 7.
It seems that there is no possible way to detect where the app is being launched from on iOS 7, but there is a way to detect if you are going to the lock-screen vs springboard. The trick is to read the screen brightness in applicationDidEnterBackground. When the app hits the background due to the lock button being pressed or an auto-lock timeout, the brightness will be 0.0 on iOS 7. Otherwise, it will be > 0 when the home button is pressed or another app launched from the multitask selector or notification center.
- (void)applicationDidEnterBackground:(UIApplication *)application {
CGFloat screenBrightness = [[UIScreen mainScreen] brightness];
NSLog(#"Screen brightness: %f", screenBrightness);
self.backgroundedToLockScreen = screenBrightness <= 0.0;
}
Now that I have an ivar holding this info, I can use it in applicationWillEnterForeground to determine my app flow.
- (void)applicationWillEnterForeground:(UIApplication *)application {
if (self.backgroundedToLockScreen) {
... // app was backgrounded to lock screen
} else {
... // app was backgrounded on purpose by tapping the home button or switching apps.
}
self.backgroundedToLockScreen = NO;
}
It is not the exact same as the iOS 6 behavior though. On iOS 6, you could inspect the UIApplicationState to detect where you were coming from, and this solution answers the similar, but not exactly the same, question of where you were going when the app was backgrounded. For example, perhaps the app was backgrounded due to a screen lock timeout, but then a notification for another app woke the device, and the user went there directly from the lockscreen, then back to my app. My app would have determined on backgrounding that the user went to the lockscreen, but when they come back they are actually coming from an active screen. For my app, this difference is negligible, but your milage may vary.
So what about older OS support? My app also supports iOS 6 so I needed to get the old behavior too. Simple. Just the application state monitoring to the foreground method:
- (void)applicationWillEnterForeground:(UIApplication *)application {
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (UIApplicationStateInactive == state || // detect if coming from locked screen (iOS 6)
self.backgroundedToLockScreen) // detect if backgrounded to the locked screen (iOS 7)
{
... // app is coming from or was backgrounded to lock screen
} else {
... // app was backgrounded on purpose by tapping the home button or switching apps
}
self.backgroundedToLockScreen = NO;
}
I am not sure how reliable the brightness reading is, or whether or not it will change in future OS builds, but in the meantime, this hack seems to be the best we can get. Hope this helps.
Actually the only proper way to set your app behavior when becoming active is via the app delegate methods.
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
These two are called when the app is running in the background and becomes active either via multitasking UI or after a call or other interruption.
When the app is opened from the Springboard and is not running in the background this method is called:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}

iPhone display screen lights not turning off automatically

I have observed that my I run my iPhone application (native) the display lights are not turning off as they usually do in other applications, I have waited for couple of minutes but it wont turn off until I exit my application.
Is there anything which I had messed up with that is not causing the automatic dimming?
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
Are the two lines to enable/disable the dimming of the screen in an iOS app. Double check and see if your app has any of these.
Put this code into application didFinishLaunchingWithOptions: method.
Have you used this in your app?
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
If so, remove it or set it to NO.

Preventing Screenshot/clearing cached data when iOS app gets backgrounded and resumed after a long time

I am building a cinema listing app, where the user can drill down thru the dataset to finally end up with a listing for a specific movie/theater/etc.
Now assume the user pauses using the app for 7 days. When reopening the app what he should not see are the listings from 7 days ago. But if the user just puts the app in background for a few minutes, the user should continue just where he left. I thought I could solve this issue by killing the app after a certain amount of time in background. This is the code:
static BOOL goingToQuit = NO;
#define KILL_IN_BACKGROUND_AFTER_SECS 300
- (void)applicationDidEnterBackground:(UIApplication *)application
{
goingToQuit = YES;
UIApplication* app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier __block bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
if(UIBackgroundTaskInvalid != bgTask) {
// Start the long-running task to kill app after some secs and return immediately.
dispatch_after( dispatch_time(DISPATCH_TIME_NOW, KILL_IN_BACKGROUND_AFTER_SECS * 1e09),
dispatch_get_main_queue(), ^{
if(goingToQuit) exit(0);
[app endBackgroundTask: bgTask];
});
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// cancel ongoing background suicide.
goingToQuit = NO;
}
What I see on my device is this: after KILL_IN_BACKGROUND_AFTER_SECS the app gets killed. After restarting the device logs show that the app got a new PID, entries showing the restart etc. Yet the device does not show the default.png startup image, but the screenshot of where the user has been before.
On the other hand if the user kills the application explicitely (double click on home button, tap & hold, click - on app) before he is restarting it the application starts with its default.png start up screen. This is the behaviour I want when killing the app programmatically.
Does anyone have an idea how to accomplish this? Any idea is highly appreciated.
BTW: As a workaround I tried to hide the main window during applicationDidEnterBackground and show it again on applicationWillEnterForeground. This, however, is highly confusing to the user when he is switching between apps.
In your app delegate's applicationDidEnterBackground you can display a view in front of the rest of your views, which the OS will grab as the last visible thing and which will be displayed when the app becomes active again (if it's still alive).
In your app delegate's applicationDidBecomeActive you can check to see if the data needs updating; if not then simply dismiss the view (animation is nice), and if so then first update (or just clear out) your data and then dismiss the view.
This is fairly common in apps. Many just use the default.png startup image, since users are accustomed to seeing it when the app launches normally.

Resources