Check for application resuming from inactive as apposed to first starting? - iphone

I have a NSTimer that I am stopping when my application resigns active, which I later restart when the application again becomes active. What I did not realise was that applicationWillResignActive would fire when my application first started (pretty obvious really). So what is happening is my NSTimer is incorrectly starting (when the application first starts). My question is, is there a way to check for the application resuming from inactive as apposed to it first starting?
- (void)applicationWillResignActive:(UIApplication *)application {
// STOP CORE TIMER
[[[self mapController] coreTimer] invalidate];
[[self mapController] setCoreTimer:nil];
}
.
- (void)applicationDidBecomeActive:(UIApplication *)application {
// START CORE TIMER
[[self mapController] setCoreTimer:[NSTimer
scheduledTimerWithTimeInterval:ONE_SECOND
target:[self mapController]
selector:#selector(timerDisplay:)
userInfo:nil
repeats:YES]];
}

There is the applicationWillEnterForeground which seems to only fire when the app comes back from the background. Just tested it, won't be called on launch.
Discussion
In iOS 4.0 and later, this method is
called as part of the transition from
the background to the active state.
You can use this method to undo many
of the changes you made to your
application upon entering the
background. The call to this method is
invariably followed by a call to the
applicationDidBecomeActive: method,
which then moves the application from
the inactive to the active state.

Related

How to properly minimize an iOS sprite kit application?

I've tried this iOS Sprite Kit tutorial and have created a similar app. However, I notice that when I press the home button to go to iOS home screen, I get a bad access exception in xCode. When I go back into the app, it starts from the beginning.
How can I properly close/minimize a Sprite Kit app to avoid that exception?
I tried this within the view controller presenting the scene, but it does not get called:
-(void)viewWillDisappear:(BOOL)animated
{
SKView * skView = (SKView *)self.view;
skView.paused = YES;
[super viewWillDisappear:animated];
}
I found out that there's Kobold Kit sprite engine built on top of Sprite Kit, after porting my project to that, i can minimize the app and restore it with the same stuff on the screen!
I believe that the proper way to handle minimizing an app is in the AppDelegate via these methods :
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive 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.
}

Stop setKeepAliveTimeout handler from being called after application came foreground?

For VOIP application we are sending PING packet to server every 10 minutes using setKeepAliveTimeout, everything works fine, however I'm not sure how to stop the handler from being called once application came foreground.
eg: Here is how I set the timeout
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
Background handler:
- (void)backgroundHandler
{
printf("10 minute time elapsed\n");
// do some action...
}
Above function is being called even after application came foreground, I have read in Apple documentation to set the handler nil to stop it. I have tried like below in applicationWillEnterForeground
[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:nil];
Still I'm getting call every 10 mins. How to handle this, Do I need to use flag only.
Any help is really appreciated.
you can do it like this
- (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.
[[UIApplication sharedApplication] clearKeepAliveTimeout];
}
You have to invoke clearKeepAliveTimeout to stop the timer. setKeepAliveTimeout: is designed to keep a voip connection on and that's why it's periodically called.

Handling Interrupts in IOS app development

I want to know how we can handle interrupts like incoming call, sms when the app is in foreground. I read the apple documentation and it says that the app will temporarily go into inactive state ie. 'applicationWillResignActive' function will be called. And things like Stopping timers , periodic tasks and running metadata queries should be performed and when it comes back to active state, again these tasks have to be disabled. What kind of tasks are they referring to when they say timers and periodic tasks. And how can we establish these coding wise. Any help will be appreciated. thanks
Yes, when receiving a temporary interruption the following method from UIApplication gets called [Apple's documentation]:
- (void)applicationWillResignActive:(UIApplication *)application
The tasks they are referring with timers and periodic tasks are these kind that are being executed periodically with a timer. For instance, you could have a timer running in the background to update the content of your view. Then, when application will resign active, is where you should stop that timer.
For instance, let's suppose that you are running a timer to perform a task every 10 seconds:
// AppDelegate.m
// When application becomes active the timer is started
- (void)applicationDidBecomeActive:(UIApplication *)application {
self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(scheduledTask:)
userInfo:nil
repeats:YES];
}
// When the application will resign active the timer is stopped
- (void)applicationWillResignActive:(UIApplication *)application {
[self.timer invalidate];
self.timer = nil;
}
The scheduled task would be:
- (void)scheduledTask:(NSTimer *)timer {
// Up to you... for instance: web service call
}

Iphone application gets stuck after unlocking screen

When i keep my application open for awhile, the iPhone/iPod locks the screen. When i unlock it my application gets stuck for like 2 seconds and then it resumes and keep functioning as usual. Why is this ? and how can i prevent it ?
To prevent this from hapenning is there any PLIST method where we could stop the process of the application when it goes to a locked screen (Might not be a better idea)
In your application delegate do you have any code that could slow down your app? Check the following methods?
-(void) applicationWillResignActive:(UIApplication *)application
-(void) applicationDidBecomeActive:(UIApplication *)application
-(void) applicationDidEnterBackground:(UIApplication*)application
-(void) applicationWillEnterForeground:(UIApplication*)application
-(void) applicationWillTerminate:(UIApplication *)application
Also use the above methods ensure you application suspends properly.
Log when your app receives a memory warning inside:
-(void) applicationDidReceiveMemoryWarning:(UIApplication *)application
Maybe when you suspend or reopen your app some there is a memory issue.
I'm not quite sure about the answer for your first question (you maybe do some heavy things inside the applicationDidBecomeActive method or the app simply reallocates memory), but i can answer the second one.
You can simply prevent the auto lock by calling:
[[UIApplication sharedApplication] setIdleTimerDisabled: YES];
A good palce for this is inside the applicationDidFinishLaunching method of the app delegate.

Screen Suddenly Turns Black

While using my app, the screen sometimes suddenly and inexplicably turns black. The screen is still powered, and if I play with the volume controls, the volume indicator shows just fine.
The only way to resolve this is to press the home button, at which point I see the following message in my log:
SpringBoard[15] : Failed to snapshot WaveDeck
When I then open the app again, it's fine.
Can anyone shed some light on this?
Update from the WaveDeck front:
We've used applicationDidEnterBackground in the app's delegate in a bad way: asking all the background operations to finish up using beginBackgroundTaskWithExpirationHandler and keeping the main runloop running inside applicationDidEnterBackground.
That way the method of applicationDidEnterBackground came to an end only after finishing all background operations, whether the app became active again or not.
So apparently the OS could not 'snapshot' the app correctly and would put on a black screen some time after returning from background state - when the delegate function of applicationDidEnterBackground ended.
I encounter a similar issue. Put the long time save operation in next runloop, so applicationDidEnterBackground return immediately, the system's snapshot mechanism works correctly.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// don't block ios's snapshoting, avoid screen suddenly turns black
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(saveAppState) object:nil];
[self performSelector:#selector(saveAppState) withObject:nil afterDelay:0];
}
- (void)saveAppState
{
[self longtimeSave];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(saveAppState) object:nil];
}