is it possible not to pause the application while in background mode (when you press the home button and the app minimizes)? I have some timers and variables that i don't want to get paused.
EDIT:
I have followed this example http://evilrockhopper.com/2010/01/iphone-development-keeping-the-ui-responsive-and-a-background-thread-pattern/
I have called a timer inside however it's not getting called when i enter background mode:
- (void)applicationDidEnterBackground:(UIApplication *)application {
if(self.viewController.timerquest != NULL)
{
if(self.viewController.timerquest.timerRunning){
// Save varibales
[self performSelectorInBackground:#selector(performLongTaskInBackground) withObject:nil];
}
}
}
- (void) performLongTaskInBackground
{
// Set up a pool for the background task.
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// perform some long task here, say fetching some data over the web.
//...
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
// Always update the components back on the main UI thread.
[self performSelectorOnMainThread:#selector(completeLongRunningTask) withObject:nil waitUntilDone:YES];
[pool release];
}
-(void) updateTimer{
// Update my timer. This method is not being called in background mode
}
What should I do?
Thanks.
use Long Running Background tasks according to manual: http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/BackgroundExecution/BackgroundExecution.html
Have a read here at the Apple non-technical documentation or at the technical reference.
Could you replace the timer with delayed background notifications?
Depending on what happens when your timers fire, you want to set up a local notification that fires at the same time the timer would have; this is useful when the timer would present something for the user to act on. As far as saving variables, you'll want to use -applicationDidEnterBackground: to save whatever state you need to, so that the correct variables can be loaded/generated when the app relaunches (which may not happen until the app has been exited and completely restarted again).
The types of tasks that are allowed to perform long running background tasks are pretty limited, specifically for things like GPS and playing audio. Everything else needs to decide on a task-by-task basis whether to simulate continued running (such as turning a timer to a local notification), pausing and saving necessary state to continue the next time the app is run, simply cancelling the task and gracefully restarting/notifying the user upon resuming the app, or asking for a finite length of time to finish a task (for things like finishing a download).
Related
i want to run one of my services in the background even my app is in foreground or background states,if i get any data from that service i want to show that one as a notification to the user. how can i proceed .
as my reserach gives me an idea to follow multi taking in iphone .
or shall i use any timer so that the method calls for particular time interval for every time
NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(notification) userInfo:nil repeats:YES];
[timer fire];
-(void)notification
{
//shall i write all of my services here
}
or shall i create any new threads like
[self performSelectorInBackground:#selector(notification) withObject:Nil];
in AppDelegate file .
or shall i need to follow any other thing plz guide me thank you.
Generally, you should consider using push notifications sent by the server to show notifications to the user when something changes. This is preferable to running in the background since it is better for system performance & battery life.
I don't understand it at all but NSTimer in my app definitely is running in background. I have a NSLog in method run by the timer and it is logging while it's in background. It's on iPhone 4 with iOS 4.2.1. I have declared location background support in Info.plist.
I read the docs and many discussions here and elsewhere and it shouldn't be possible. Is it an iOS bug? Or undocumented feature? I don't want to use it and find out in near future, for example with coming of iOS 4.3 that Apple silently "fixed" it and the app won't be working.
Does anybody know more about it?
NSTimer is going to fire whenever the main runloop is running. Apple makes no promises that I know of to unschedule timers or to prevent the main runloop from running. It's your responsibility to unschedule your timers and release resources when you move to the background. Apple isn't going to do it for you. They may, however, kill you for running when you are not supposed to or using too many seconds.
There are many holes in the system that will allow an app to run when it isn't authorized to. It would be very expensive for the OS to prevent this. But you cannot rely on it.
You can have a timer fire while in background execution mode. There are a couple of tricks:
You need to opt into background execution with beginBackgroundTaskWithExpirationHandler.
If you create the NSTimer on a background thread, you need to add it to the mainRunLoop manually.
- (void)viewDidLoad
{
// Avoid a retain cycle
__weak ViewController * weakSelf = self;
// Declare the start of a background task
// If you do not do this then the mainRunLoop will stop
// firing when the application enters the background
self.backgroundTaskIdentifier =
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundIdentifier];
}];
// Make sure you end the background task when you no longer need background execution:
// [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Since we are not on the main run loop this will NOT work:
[NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(timerDidFire:)
userInfo:nil
repeats:YES];
// This is because the |scheduledTimerWithTimeInterval| uses
// [NSRunLoop currentRunLoop] which will return a new background run loop
// which will not be currently running.
// Instead do this:
NSTimer * timer =
[NSTimer timerWithTimeInterval:0.5
target:weakSelf
selector:#selector(timerDidFire:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer
forMode:NSDefaultRunLoopMode];
// or use |NSRunLoopCommonModes| if you want the timer to fire while scrolling
});
}
- (void) timerDidFire:(NSTimer *)timer
{
// This method might be called when the application is in the background.
// Ensure you do not do anything that will trigger the GPU (e.g. animations)
// See: http://developer.apple.com/library/ios/DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW47
NSLog(#"Timer did fire");
}
Notes
Apps only get ~ 10 mins of background execution - after this the timer will stop firing.
As of iOS 7 when the device is locked it will suspend the foreground app almost instantly. The timer will not fire after an iOS 7 app is locked.
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
}
I need to schedule a task in background when the application enter background state.
I have to do this in order to call a remote service each x time and then show a local notification when some event happend with the remote service.
(I know it's looks like RPN, yes it is, but for some reason I am not able to use PRM)
I tried this code :
- (void)applicationDidEnterBackground:(UIApplication *)application{
[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(void){
remoteServiceCallThread = [[NSThread alloc] initWithTarget:self selector:#selector(doRemoteCall:) object:nil];
[remoteServiceCallThread start];
}];
}
- (void)applicationWillEnterForeground:(UIApplication *)application{
[remoteServiceCallThread cancel];
}
I put breakpoint in the doRemoteCall selector, put is not working.
Maybe my approach is not the best one. If you have any other hack to doing this operation like I describe it I'll take it.
Thank you.
You are not starting the thread, it's initialization code is at the expiration handler block which will be called right before the app is shut down with a timeout:
A handler to be called shortly before the application’s remaining
background time reaches 0. You should use this handler to clean up and
mark the end of the background task. Failure to end the task
explicitly will result in the termination of the application. The
handler is called synchronously on the main thread, thus blocking the
application’s suspension momentarily while the application is
notified.
The task should be active for 10 minutes only (that is driven by iOS) if your app is not supporting one of the background modes (gps, audio, voip).
You also need to keep the returned UIBackgroundTaskIdentifier reference to be able to mark it as ended if the user brings the app to foreground or when task time is going to the end (that's when the handler block is called).
I have a question that we might answer together i have a tickertape in my iphone app (Like those stick tickers) and i use a NSThread to keep the memory away from the main thread so it will not slow down the app. Now the thing is it does its job well but when i scroll on a UITableView that i have on the same view i notice that my ticker tape animation stops to work.
ViewController.m (Main view of this object has the ticker tape on it)
-(void)startTicker {
[NSThread detachNewThreadSelector:#selector(start) toTarget:ticker withObject:nil];
}
TickerView.c (This handles the tickertape animation)
// Called from the viewcontroller
-(void) start {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self performSelectorOnMainThread:#selector(loop) withObject:nil waitUntilDone:YES];
[pool release];
}
-(void)loop {
timerHandle = [NSTimer scheduledTimerWithTimeInterval:.01f target:self selector:#selector(render) userInfo:nil repeats:YES];
}
-(void) render {
// Does a *** load of calculations here and moves the items in the tickertape..
}
My Question: How can i prevent the UITableview or any other view / touch event to block this thread from updating the tickertape animation ?.
Your NSTimer is not running on a background thread, but on the main thread. It will block anytime something else runs on the main thread. -performSelectorOnMainThread: means that anything done within the method called will run on the main thread.
To make your loop truly independent of the main thread, you could set up a while loop within your start method that sleeps for a given interval on every pass, then calls your render method. You'd need to make sure that all user interface updates within your render method get performed on the main thread, but make waitUntilDone NO for those method calls. I've also done this using NSOperations, where as one operation finishes I add another to the queue.
Also, running this render operation 100 times per second is excessive. I'd back that down a bit, or even better, look at using Core Animation for your ticker to make your drawing more efficient.