I have a background task that should return an array of courses that is then sent to the apple watch. I'm calling the task inside didReceiveMessage
via WatchConnectivity
.
The background task needs to perform a few operations such as opening the realm database, querying the results and accessing the documents directory before returning the response to the courses dictionary. The logic seems to work as the watch outputs its getting the course data. The problem is that I don't think the background task is actually calling the method getWatchCourses()
DispatchQueue.global().async {
var foundCourses = [[String : Any]]()
let application = UIApplication.shared
backgroundTask = application.beginBackgroundTask(withName: "app.test.getCourses") {
let watchModel = WatchCourseModel()
let courses = watchModel.getWatchCourses()
print("Courses: \(courses)")
foundCourses.append(contentsOf: courses)
}
replyHandler(["response": foundCourses])
application.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
This also doesn't work if the getWatchCourses()
result is hardcoded. Can the app perform this logic when in the background or should it work?
It's also worth pointing out that nowhere online has this documented, They always refer to sending simple text responses back to the watch, not something processor intensive :(
Thanks
You are doing your operation in trailing closure which is used to clean up. And more thing that you are ending background task as soon as it starts so your closure will never call.
Here is working example how the background task works
var backgroundTaskIdentifier:UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
var updateTimer: Timer?
Now when you start your operation for an example running timer
updateTimer = Timer.scheduledTimer(timeInterval: 0.5, target: self,
selector: #selector(calculateNextNumber), userInfo: nil, repeats: true)
// register background task
beginBackgroundTask()
and when You end the timer end the background task; should always end background task without fail
func beginBackgroundTask () {
backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in
self?.endBackgroundTask() // It will call to cleanup
})
assert(backgroundTaskIdentifier != UIBackgroundTaskInvalid)
}
func endBackgroundTask () {
UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
backgroundTaskIdentifier = UIBackgroundTaskInvalid
}
So In your case
Note: Also take note of the time limit given by apple to perform your background task
EDIT
Make sure you have enabled background capability form project settings
Try like
beginBackgroundTask()
let watchModel = WatchCourseModel()
let courses = watchModel.getWatchCourses()
print("Courses: \(courses)")
foundCourses.append(contentsOf: courses)
endBackgroundTask()
If you check the documentation you will see that the full function prototype is beginBackgroundTask(withName:expirationHandler:)
The code you have specified via the trailing closure is the expirationHandler
- it is the code that is called if you don't call endBackgroundTask
before the permitted background execution time is exhausted. The expiration handler gives you a final chance to perform any clean up before your app is terminated for exceeding its background time.
Since you almost immediately call endBackgroundTask
and return from the function, the expiration handler won't be called.
What you actually want is something like:
var foundCourses = [[String : Any]]()
let application = UIApplication.shared
backgroundTask = application.beginBackgroundTask(withName: "app.test.getCourses") {
DispatchQueue.global().async {
let watchModel = WatchCourseModel()
let courses = watchModel.getWatchCourses()
print("Courses: \(courses)")
foundCourses.append(contentsOf: courses)
replyHandler(["response": foundCourses])
application.endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
This starts a background task, you then perform the work asynchronously and pass the result back to the watch and end the background task.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With