I have some background threads in my app where I have some NSTimers running in NSDefaultRunLoopMode mode. When I press home button the app goes to background.
If I don't call beginBackgroundTaskWithExpirationHandler: in applicationDidEnterBackground: the threads get suspended when the application is in background. But if I call beginBackgroundTaskWithExpirationHandler: the threads don't get suspended even after the expiration handler returns.
Why is it that background threads keep running in one case while in another case they don't? When will the background threads get suspended in the second case?
According this document beginBackgroundTaskWithExpirationHandler:
This method lets your app continue to run for a period of time after it transitions to the background.
That why if you call beginBackgroundTaskWithExpirationHandler: in applicationDidEnterBackground: the threads don't get suspended.
And
Each call to this method must be balanced by a matching call to the endBackgroundTask: method. Apps running background tasks have a finite amount of time in which to run them. (You can find out how much time is available using the backgroundTimeRemaining property.) If you do not call endBackgroundTask: for each task before time expires, the system kills the app. If you provide a block object in the handler parameter, the system calls your handler before time expires to give you a chance to end the task.
So the background threads get suspended in the second case when you use beginBackgroundTaskWithExpirationHandler: right way with endBackgroundTask: by adding endBackgroundTask: outside of expiration handler.
Related
If an application starts to perform some activity in the foreground, then it moves to the background and continues to execute for the 30 seconds that the OS lets it run for, but then within that 30 seconds it has not completed what it was doing.
Then what happens when the app next comes to the foreground? Does whatever processing it was in the middle of doing when the 30 seconds was up automatically get resumed at the point it got suspended by the OS when in the background and the 30 seconds finished?
(Similar question - suppose the app calls UIApplication.setMinimumBackgroundFetchInterval().
Then if the user moves the app to the background, it runs for 30 seconds then stops, then the OS runs it in the background due to setMinimumBackgroundFetchInterval having been called, does it resume exactly what it was doing at the end of the 30 seconds?)
No, it does not continue. It seems that the answers you are looking for can be found in this parts of the documentation (emphasis mine), depending on how you transfer tasks to the background :
https://developer.apple.com/documentation/uikit/uiapplication/1623051-beginbackgroundtask
Each call to this method must be balanced by a matching call to the endBackgroundTask(_:) method. Apps running background tasks have a finite amount of time in which to run them. (You can find out how much time is available using the backgroundTimeRemaining property.) If you do not call endBackgroundTask(_:) for each task before time expires, the system kills the app. If you provide a block object in the handler parameter, the system calls your handler before time expires to give you a chance to end the task.
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623125-application
When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. In practice, your app should call the completion handler block as soon as possible after downloading the needed data. If you do not call the completion handler in time, your app is terminated.
My app while in background receive pushes to trigger some background tasks, scheduled in a NSOperationQueue.
The first NSOperation terminates correctly, but the second doesn't terminate, it seems like the task is paused, and when I put the app back in foreground the operation can terminate like it should.
Is there restrictions for background tasks ? (The tasks take about 2 or 3 seconds to execute)
Thank you
you have enable any of the background service like Location , Background fetch , Remote Notification to enable active your app in background mode. Please below apple link where you may get more idea -
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
I have an instance of AVAudioRecorder and I have noticed that when the user closes the app too fast with a larger recording the file does not get saved properly.
This even happens when I call [recorderObject stop] in the main thread and the file gets saved locally.
I have also tried moving the file after the recording has stopped (in the (void)audioRecorderDidFinishRecording:successfully: method). But I have noticed that when I do the move with NSFileManager in a background thread with high priority, it too doesn't always finish.
Is there a way for me to insure that the files get saved, even if the user exits the app shortly after finishing a longer recording?
Thanks
Review Apple's documentation for executing tasks in the background.
Apps moving to the background are expected to put themselves into a
quiescent state as quickly as possible so that they can be suspended
by the system. If your app is in the middle of a task and needs a
little extra time to complete that task, it can call the
beginBackgroundTaskWithName:expirationHandler: or
beginBackgroundTaskWithExpirationHandler: method of the UIApplication
object to request some additional execution time. Calling either of
these methods delays the suspension of your app temporarily, giving it
a little extra time to finish its work. Upon completion of that work,
your app must call the endBackgroundTask: method to let the system
know that it is finished and can be suspended.
just wondering what will happen after performFetchWithCompletionHandler, will my app stay in the memory, or will it get purged immediately? I've googled but no one seems to be caring about this.
When this method is called, your app has up to 30 seconds of wall-clock time to perform the download operation and call the specified completion handler block. In practice, your app should call the completion handler block as soon as possible after downloading the needed data. If you do not call the completion handler in time, your app is terminated. More importantly, the system uses the elapsed time to calculate power usage and data costs for your app’s background downloads. If your app takes a long time to call the completion handler, it may be given fewer future opportunities to fetch data in the future.
Straight from Apple documentation - UIApplication Delegate
Is applicationDidEnterBackground ALWAYS called before applicationWillTerminate in an iOS app? I know that applicationWillTerminate is not always called (multitasking) - but when it is called, is applicationDidEnterBackground ALWAYS called first? I don't want to duplicate code unnecessarily by including it in applicationWillTerminate if it is already included in applicationDidEnterBackground, for an app that supports multitasking.
in ios 4.0 and later applicationDidEnterBackground is called instead of applicationWillTerminate so you don't have to call both of them. Here is the portion of the Apple docs:
Discussion
In iOS 4.0 and later, this method is called instead of the
applicationWillTerminate: method when the user quits an application
that supports background execution. You should 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. You should also
disable updates to your application’s user interface and avoid using
some types of shared system resources (such as the user’s contacts
database). It is also imperative that you avoid using OpenGL ES in the
background.
Your implementation of this method has approximately five seconds to
perform any tasks and return. If you need additional time to perform
any final tasks, you can request additional execution time from the
system by calling beginBackgroundTaskWithExpirationHandler:. In
practice, you should return from applicationDidEnterBackground: as
quickly as possible. If the method does not return before time runs
out your application is terminated and purged from memory.
You should perform any tasks relating to adjusting your user interface
before this method exits but other tasks (such as saving state) should
be moved to a concurrent dispatch queue or secondary thread as needed.
Because it's likely any background tasks you start in
applicationDidEnterBackground: will not run until after that method
exits, you should request additional background execution time before
starting those tasks. In other words, first call
beginBackgroundTaskWithExpirationHandler: and then run the task on a
dispatch queue or secondary thread.
The application also posts a
UIApplicationDidEnterBackgroundNotification notification around the
same time it calls this method to give interested objects a chance to
respond to the transition.
For more information about how to transition gracefully to the
background, and for information about how to start background tasks at
quit time, see iOS App Programming Guide.
Hope this helps clear the issue for you man.
Adrian
Here is the link to the technical note that is available on developer section. It is dealing with networking and multitasking. The actual method used in this doc deals with only applicationDidEnterBackground and since iOS 5 they have a system called watchdog which terminates the app if the network is unresponsive automatically. Hence there is no need to actually call applicationWillTerminate and try to execute codes to allow your app to finish its task before the app is terminated. The app will enter the background and will continue its task until the last task is completed. I hope that makes sense, but here is the link. Please read the watchdog section.
https://developer.apple.com/library/ios/#technotes/tn2277/_index.html#//apple_ref/doc/uid/DTS40010841
Hope this helps. :)