Reputation: 569
my swift app needs to run a piece of code periodically even while being in the background. What is the best way to accomplish that?
i tried DispatchQueue.global(qos: .background).async
but that didnt work
new try:
i added this to my ViewController:
private var time: Date?
private lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .long
return formatter
}()
func fetch(_ completion: () -> Void) {
time = Date()
completion()
}
and this to my AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplicationBackgroundFetchIntervalMinimum)
// Override point for customization after application launch.
return true
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let tabBarController = window?.rootViewController as? UITabBarController,
let viewControllers = tabBarController.viewControllers
{
for viewController in viewControllers {
if let fetchViewController = viewController as? ViewController {
fetchViewController.fetch {
completionHandler(.newData)
print("fired")
}
}
}
}
}
and put a breakpoint on completionHandler(.newData)
.
But when i run the app, the breakpoint never gets triggered. and the print statement never executed.
Upvotes: 3
Views: 7034
Reputation: 19758
iOS does not allow your app to keep running processes as and when you like whilst the app is backgrounded. When it is first backgrounded you will have a short amount of time to perform some tasks (around a couple of minutes) before it will stop.
Then, you need to use background fetch to periodically fetch new information for your app.
There is a good tutorial on the various background modes supported by iOS on teh Ray Wenderlich website: RayWenderlich - Background modes.
There is also a guide on Apples developer portal that explains what you can and cannot do while the app is backgrounded.
Implementing Long-Running Tasks
For tasks that require more execution time to implement, you must request specific permissions to run them in the background without their being suspended. In iOS, only specific app types are allowed to run in the background:
- Apps that play audible content to the user while in the background, such as a music player app
- Apps that record audio content while in the background
- Apps that keep users informed of their location at all times, such as a navigation app
- Apps that support Voice over Internet Protocol (VoIP)
- Apps that need to download and process new content regularly
- Apps that receive regular updates from external accessories
- Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services.
Declaring the services lets the system know which services you use, but in some cases it is the system frameworks that actually prevent your application from being suspended.
UPDATE:
Firstly, I wouldn't put my refresh code in a ViewController, the VC may not be in memory during a background fetch operation. Create a separate class or something that deals with fetching and storing the data and then on your ViewControllers viewWillAppear
function, load the latest data available.
For testing background fetch operations, in xcode, select Debug from the menu and then select Simulate Background Fetch. It will start the app and call the performFetchWithCompletionHandler
function.
Upvotes: 4