Can't endBackgroundTask: no background task exists with identifier, or it may have already been ended
Objective CIos7Xcode5Objective C Problem Overview
I am using background task to run the timer in the background to update the user's location. It's declared as:
UIBackgroundTaskIdentifier bgTask;
in the header file, and initialized as:
bgTask = UIBackgroundTaskInvalid;
But still, I am getting this message in the gdb:
> Can't endBackgroundTask: no background task exists with identifier 23dc, or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
Why? And how can I solve this?
Objective C Solutions
Solution 1 - Objective C
I lose many days looking for the piece of code or framework that was causing this warning in the debug console Can't end BackgroundTask: no background task exists with identifier 2 (0x2), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.
Finally I've created an empty project Single View App. Only code generated by Xcode, I run the app on simulator, put it in background and I see the same warning. So I can say it's an iOS 13 issue. I hope Apple will fix it quickly because in Crashlytics I found some crash in my app caused by it.
Solution 2 - Objective C
In Xcode, switch to the breakpoint navigator (View > Navigators > Show Breakpoint Navigator) then push the + button in the bottom left and select Add Symbolic Breakpoint and enter “UIApplicationEndBackgroundTaskError” as the symbol.
Solution 3 - Objective C
You need to set bgTask = UIBackgroundTaskInvalid
in two moments
- In the expiration handler.
- After finishing your task.
I believe you are missing any of those two moments and that is why you are getting that error.
See apple example code:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
// Clean up any unfinished task business by marking where you
// stopped or ending the task outright.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Do the work associated with the task, preferably in chunks.
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
link: https://developer.apple.com/documentation/backgroundtasks/bgtask?language=objc
Solution 4 - Objective C
Reproduced, here is my entire app:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
return true
}
}
And when I take it to background I get the same message. No storyboard or any other noise.
Solution 5 - Objective C
Are you using location update in the background?
If yes, add the below code at the time of getting location authorization from the user - Apple changed the default for allowsBackgroundLocationUpdates
to NO
from iOS 9 onwards.
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) {
locationManager.allowsBackgroundLocationUpdates = YES;
}
Please make sure that you activated the 'Location updates' for background modes under your project 'Signing & Capabilities'. Otherwise it will crash.
Solution 6 - Objective C
Using Swift 5 - IOS 13.2.2 - Xcode 11.2 beta 2 (11B44) I managed to get rid of this error by
-
enabling Push notifications in the Capabilities of the app
-
Import the UserNotifications framework
-
then add this code to
> func application(_ application: UIApplication, > didFinishLaunchingWithOptions launchOptions: > [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
// If granted comes true you can enabled features based on authorization.
guard granted else { return }
DispatchQueue.main.async {
application.registerForRemoteNotifications()
}
}
Solution 7 - Objective C
Regarding the “Can’t end BackgroundTask: no background task exists with identifier ...” message, as others have said, this can be a red herring, unrelated to what you’re doing.
Regarding your goal of trying to periodically retrieve the user’s location, rather than trying to keep your app running in the background with a timer, you should instead avail yourself of various services for updating the user location in the background, such as the visits location service or the significant change location service. With these services, the OS can wake your app when there is a change in the user’s location.
Solution 8 - Objective C
I had the same issue and figured out the cause and solution!
Apple has fixed this issue in iOS 13.4 GM though I have workaround for the earlier versions.
While you should embrace using scenes when your app is run under iOS 13 and later, you can fully opt-out while you still support iOS 12 or earlier.
- First, completely remove the “
Application Scene Manifest
” entry from Info.plist. - If there is a scene delegate class, remove it.
- If there are any scene related methods in your app delegate, remove those methods.
- If missing, add the property
var window: UIWindow?
to your app delegate. - Your app should now only use the app delegate and under iOS 13 it should have the same life cycle as iOS 12.
Happy coding!
Solution 9 - Objective C
I think there is a bug working with xcode 11.2 and the swiftUI framework because I always get the
> "Can't end BackgroundTask: no background task exists with > identifier..."
message even when my app is not working with background tasks! The good news is that this only stops my app when executing from xcode; use the 'continue program execution' button and the app will be running again.
Solution 10 - Objective C
This has been fixed in iOS 13.4 GM.