I have a hard time to understand my iPhone Application strange behavior in iOS4.
Exit my app with Home button -> applicationWillResignActive , didEnterBackground is called,
Open my app -> applicationDidBecomeActive , didEnterForground is called. Everything is normal here.
Exit my app with Home button -> applicationWillResignActive , didEnterBackground is called,
Double tap Home button, exit my app with "minus" button.
Open my app -> applicationDidBecomeActive , didEnterForground is called.
Exit my app with Home button -> applicationWillTerminate is called.
Debugger stopped.
Program exited with status value:0.
(4, 5 , 6) . What is really happening when I press minus button? Shouldn't application terminate and next time I open application (BOOL)application:(UIApplication*)application didFinishLaunching be called?
Can anyone help me understand this?
If the application have already entered the inactive state (applicationWillResignActive+didEnterBackground) you will not get any further notifications if the application is terminated.
I would though expect your application to stop completely after step 4, but since you didn't get the debugger terminated message (as in step 7) somehow the application didn't terminate fully.
The WWDC 2010 Session 105 - Adopting Multitasking on iPhone OS, Part 1 Video explains the application state transitions extremely well.
Also see iOS Debugging Magic (Technical Note TN2239) and Understanding and Analyzing iPhone OS Application Crash Reports (Technical Note TN2151).
Jeff
Related
When I pressing "home" button, app calling - (void)applicationWillResignActive:(UIApplication *)application, ok its good, but when I wait for a some time (10-15 mins), app starting from first loading screen, why? I have added:
[UIApplication sharedApplication].idleTimerDisabled = YES;
But not success. I think it goes to suspended mode, how do I prevent this? Thanks.
It means that your app has been killed by the system.
You can't prevent it completely, the system kills background apps when it needs more memory, but you can do something like this:
free as memory as you can when the app goes in background: doing this, when the system needs memory, your app won't be one of the first to be killed because its footprint is low.
Since you can't be sure that your app won't be killed, use state preservation / restoration: Link
EDIT:
since your app needs to reproduce audio in the background (as written in the comments) I give you some extra advices.
remember to register your app background mode (from this link: Multitasking guide) --> "by including the UIBackgroundModes key (with the value audio) in its Info.plist file"
the app continues to work in the background since it's playing audio, but when the audio is suspended the app is suspended too (it means that it can be killed). So, you must use state preservation to restore it when the user comes back.
Another extract:
"When the UIBackgroundModes key contains the audio value, the system’s media frameworks automatically prevent the corresponding app from being suspended when it moves to the background. As long as it is playing audio or video content, the app continues to run in the background. However, if the app stops playing the audio or video, the system suspends it."
You app has exited. If you want it to come back to where you left off you'll have to preserve the state somehow, check on launch, and then restore the state.
I've got a tricky question. In my app user can change if he want app to run in background or not. If yes - it should work until user kills it. If not - it should work until user presses home button, and SHOULD work after locking screen with top button.
So, there is a line in plist file called "application does not run in background". If i make it "YES" - app running until home button pressed, and still working after locking screen. Perfect. If i make it "NO" - app running all the time until i kill it. Perfect.
But i guess you can't change plist value from app. Well i've found a way to do that with applicationDidEnterBackground:
if (userDontWantItRunInBackground) { exit(0); }
But there is a problem with that (except Apple don't recommend it):
if "application does not run in background" = YES:
applicationDidEnterBackground is NOT CALLED on locking the screen
if "application does not run in background" = NO:
applicationDidEnterBackground is CALLED on locking the screen
It makes no sense! This doesn't allow me to make app running on locked screen!
In iOS 4, you can't avoid Idle time sleep if your app wish.
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
Here is more information about background execution in iOS:
More:
When press the lock button in app,system will call :
-(void) applicationWillResignActive:(UIApplication *)application and
-(void) applicationDidEnterBackground:(UIApplication *)application
So how can I do to make my app only resignActive but not enter background,and I can run my timer when screen locked(Timer can't execute in background mode).
One method is set the property "Application does not run in background" in .plist to YES,it worked, but my app can never enter background again,however I want it will enter background when press the home button.
Update: I want to play some music in my app at a certain time,just like a music alarm,and I still want it works fine when the screen locked,because keep the screen on may waste a lot of battery,and I don't need to do any thing when user press the home button and exit my app.
Open your Info.plist file and add Application does not run in background. Set value to YES.
Application must have special privileges to do any processing in background such as Audio service/Voip service/Location service.
"I can run my timer when screen locked(Timer can't execute in background mode)"
you cannot run a timer in background which will keep running without using any tentrum and doing so...apple will not accept your application on appstore - that's the worst side if you are targeting appstore...
You can not prevent your app from entering the background. This is decided by the operating system (iOS) and is out of control from applications. However, from reading your updated question, I don't think this is what you need to do.
You can execute background tasks with [UIApplication beginBackgroundTaskWithExpirationHandler;] (see reference). If you want to have something happening after a certain interval, check out [UIApplication scheduleLocalNotification:].
Some services such as VOIP, Audio and CoreLocation are allowed to run in background. Using these for other than their intended purposes (for example, playing silent audio) may risk your app being rejected.
Note that there is nothing you can do to prevent your application from entering the background. It is just that some tasks are allowed to execute in the background. Because of this, you cannot do GUI operations and NSTimers will probably not fire (at least I know some cases where they don't).
It would help knowing what you want to run in the background in order to suggest a solution.
Unless you are playing audio BEFORE the move to background you cannot start audio playback when the app is moved to the background or the screen is locked (which has some weird specifics) suffice to say, its as if you were in the background without actually receiving the applicationDidEnterBackground notification.
The best you can do is schedule a local notification, but in this case your music is limited to 30 seconds and must be part of your application bundle.
Playing around with Timers, and trying to make them behave right when app is sent to background, killed etc.
Judging by the generated comments in xcode, you should disable/invalidate timers on resignActive/enterBackground events.
However, i havent done that yet, but checked what happens to my timer when i click the home button and then re-enter the app.
I basically have a method in my view that the timer triggers every second:
NSLog(#"workedTimTimerTick workedTime; %#", timeString);
And when i exit the app, the output stops, when i re-enter the app, the output starts again...
Since i'm not doing anything code-wise to the timer on those lifecycle events, how come it stops getting called?
Input appreciated!
Your app is suspended when it enters background mode (Application States and Transitions).
Your timer won't fire when the app is in background and the time spent in background isn't taken into account for the timer delay.
I would like to use Instruments to check for any memory leaks in my iPhone app.
But as soon as I'm pressing the record button in Instruments, the Xcode status bar is mentioning:
GDB: Program received signal: "SIGKILL".
My app is of course not responding anymore on my iPhone.
Does anyone know what the problem is?
Step 1 - Quit the Instruments, Xcode and Simulator.
Step 2 - Start Xcode.
Step 3 - Go to Run -> Run with performance tool -> Leaks.
Thats it!