Processes & Concurrency

RSS for tag

Discover how the operating system manages multiple applications and processes simultaneously, ensuring smooth multitasking performance.

Concurrency Documentation

Posts under Processes & Concurrency subtopic

Post

Replies

Boosts

Views

Activity

Processes & Concurrency Resources
General: DevForums subtopic: App & System Services > Processes & Concurrency Processes & concurrency covers a number of different technologies: Background Tasks Resources Concurrency Resources — This includes Swift concurrency. Service Management Resources XPC Resources Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com"
0
0
164
Jul ’25
BGContinuedProcessingTask register block not called, submit does not throw an error
I implemented BGContinuedProcessingTask in my app and it seems to be working well for everyone except one user (so far) who has reached out to report nothing happens when they tap the Start Processing button. They have an iPhone 12 Pro Max running iOS 26.1. Restarting iPhone does not fix it. When they turn off the background processing feature in the app, it works. In that case my code directly calls the function to start processing instead of waiting for it to be invoked in the register block (or submit catch block). Is this a bug that's possible to occur, maybe device specific? Or have I done something wrong in the implementation? func startProcessingTapped(_ sender: UIButton) { if isBackgroundProcessingEnabled { startBackgroundContinuedProcessing() } else { startProcessing(backgroundTask: nil) } } func startBackgroundContinuedProcessing() { BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: .main) { @Sendable [weak self] task in guard self != nil else { return } startProcessing(backgroundTask: task as? BGContinuedProcessingTask) } let request = BGContinuedProcessingTaskRequest(identifier: taskIdentifier, title: title, subtitle: subtitle) request.strategy = .fail if BGTaskScheduler.supportedResources.contains(.gpu) { request.requiredResources = .gpu } do { try BGTaskScheduler.shared.submit(request) } catch { startProcessing(backgroundTask: nil) } } func startProcessing(backgroundTask: BGContinuedProcessingTask?) { // FIXME: Never called for this user when isBackgroundProcessingEnabled is true }
8
0
155
2h
[iOS 26 Beta] BGTaskScheduler.supportedResources incorrectly reports no GPU support for BGContinuedProcessingTask on capable hardware
Testing Environment: iOS: 26.0 Beta 7 Xcode: Beta 6 Description: We are implementing the new BGContinuedProcessingTask API introduced in iOS 26. We have followed the official documentation and WWDC session guidance to configure our project. The Background Modes (processing) and Background GPU Access capabilities have been added in Xcode. The com.apple.developer.background-tasks.continued-processing.gpu entitlement is present and set to in the .entitlements file. The provisioning profile details viewed within Xcode explicitly show that the "Background GPU Access" capability and the corresponding entitlement are included. Despite this correct configuration, when running the app on supported hardware (iPhone 16 Pro), a call to BGTaskScheduler.supportedResources.contains(.gpu) consistently returns false. This prevents us from setting request.requiredResources = .gpu. As a result, when the BGContinuedProcessingTask starts without the GPU resource flag, our internal Metal-based exporter attempts to access the GPU and is terminated by the system, throwing an IOGPUMetalError: Insufficient Permission (to submit GPU work from background). We have performed extensive debugging, including a full reset of the provisioning profile (removing/re-adding capabilities, toggling automatic signing, cleaning build folders, and reinstalling the app), but the issue persists. This strongly suggests a bug in the iOS 26 beta where the runtime is failing to correctly validate a valid entitlement. Additionally, we've observed inconsistent behavior across devices. On an A16-based iPad, the task submits successfully (BGTaskScheduler.submit does not throw an error), but the launch handler is never invoked by the system. On the iPhone 16 Pro, the handler is invoked, but we encounter the supportedResources issue described above. This leads us to ask for clarification on the exact hardware requirements for this feature. We hypothesize that it may be limited to devices that support Apple Intelligence (A17 Pro and newer). Could you please confirm this and provide official documentation on the device support criteria? Steps to Reproduce: Create a new Xcode project. In Signing & Capabilities, add "Background Modes" (with "Background processing" checked) and "Background GPU Access". Add a permitted identifier (e.g., "com.company.test.*") to BGTaskSchedulerPermittedIdentifiers in Info.plist. In application(_:didFinishLaunchingWithOptions:) or a ViewController's viewDidLoad, log the result of BGTaskScheduler.shared.supportedResources.contains(.gpu). Build and run on a physical, supported device (e.g., iPhone 16 Pro). Expected Results: The log should indicate that BGTaskScheduler.shared.supportedResources.contains(.gpu) returns true. Actual Results: The log shows that BGTaskScheduler.shared.supportedResources.contains(.gpu) returns false.
6
0
279
1d
Does BGAppRefreshTask Run After a User Force-Quits the App? Seeking Official Clarification
I’m looking for an authoritative answer on how BGAppRefreshTask behaves after a user force-quits an app (swipes it away in the App Switcher). My app relies on early-morning background refresh to prepare and schedule notifications based on user-defined thresholds and weather forecasts. Behavior across devices seems inconsistent, however: sometimes a scheduled background refresh still runs, and other times it appears completely blocked. Apple’s documentation doesn’t clearly state what should happen, and developer discussions conflict. Could someone from Apple please clarify: Will a previously scheduled BGAppRefreshTask run after the user force-quits the app? If not, is there a recommended alternative for time-sensitive updates that must schedule user alerts? What is the expected system behavior regarding the predictability of background refresh after a force-quit? A definitive answer would help ensure the app aligns with intended system behavior. Thanks!
7
0
320
1d
BGTaskScheduler Terminated due to memory issue
Hello everybody! I'm currently working on a Bluetooth Low Energy Sync that is using BGTaskScheduler & successfully running periodically in the Background on iOS 26. I did watch this years WWDC Session 227 (Finish tasks in the background) & follow the recommendations as suggested. Currently, the App is only using 37 Mb (iPhone 12 mini) & no Location or other services are running in Background. However, when opening Safari & scrolling through some webpages, the App is killed because of "Terminated due to memory issue". I profiled the App & followed advice when it comes to reducing the memory footprint of the App. Are there any additional steps I can take to prevent the App being killed? Are there any recommendations for periodically scheduled Tasks when it comes to the Interval? Do more frequent Tasks (30min compared to one or two hours) have any impact? I tried many different schedules but none seem to make a difference. From my observation, the App is first suspended & eventually killed because of the Memory Pressure. Any hints, suggestions or recommendations are highly appreciated! Thanks a lot for the support!
3
0
100
3d
MacOS 26 TestFlight SIGKILLs app when updating
We're developing an Electron app for MacOS App Store. When updating our app through TestFlight, TestFlight prompts "Close This App to Update", and when I click "Continue" our app would be "Terminated" for update. Now this is where things go wrong. On MacOS 15 our app seems to be gracefully terminating (We attached it with lldb and it shows that our app returns with 0 when we click "Continue") which is fine. However for MacOS 26 though, it seems that TestFlight just directly SIGKILLs our app (indicated by lldb), which means that all of our app's child processes are left orphaned. Even worse, our app is singleton, which means that when the app relaunches it fails, because the leftover child processes from the previously SIGKILLed session is still alive, and even if we want to kill those orphaned child processes we can't because our app is sandboxed thus cannot kill processes outside of the current sandbox. We captured output from log stream (app name redacted): 12-02 22:08:16.477036-0800 0x5452     Default     0x5a4a7              677    7    installcoordinationd: [com.apple.installcoordination:daemon] -[IXSCoordinatorProgress setTotalUnitsCompleted:]: Progress for coordinator: [com.our.app/Invalid/[user-defined//Applications/OurApp.app]], Phase: IXCoordinatorProgressPhaseLoading, Percentage: 99.454 123: Attempt to set units completed on finished progress: 214095161 2025-12-02 22:08:16.483056-0800 0x53ba     Default     0x5a5c9              167    0    runningboardd: (RunningBoard) [com.apple.runningboard:connection] Received termination request from [osservice<com.apple.installcoordinationd(274)>:677] on <RBSProcessPredicate <RBSProcessBundleIdentifierPredicate "com.our.app">> with context <RBSTerminateContext| explanation:installcoordinationd app:[com.our.app/Invalid/[user-defined//Applications/OurApp.app]] uuid:A3BC0629-124E-4165-ABB7-1324380FC354 isPlaceholder:N re portType:None maxTerminationResistance:Absolute attrs:[ 2025-12-02 22:08:16.488651-0800 0x53ba     Default     0x5a5c9              167    7    runningboardd: (RunningBoard) [com.apple.runningboard:ttl] Acquiring assertion targeting system from originator [osservice<com.apple.installcoordinationd(274)>:677] with description <RBSAssertionDescriptor| "installcoordinationd app:[com.our.app/Invalid/[user-defined//Applications/OurApp.app]] uuid:A3BC0629-124E-4165-ABB7-1324380FC354 isPlaceholder:N" ID:167-677-1463 target:system attributes:[ 2025-12-02 22:08:16.489353-0800 0x53ba     Default     0x5a5c9              167    0    runningboardd: (RunningBoard) [com.apple.runningboard:process] [app<application.com.our.app.485547.485561(501)>:2470] Terminating with context: <RBSTerminateContext| explanation:installcoordinationd app:[com.our.app/Invalid/[user-defined//Applications/OurApp.app]] uuid:A3BC0629-124E-4165-ABB7-1324380FC354 isPlaceholder:N reportType:None maxTerminationResistance:Absolute attrs:[ 2025-12-02 22:10:23.920869-0800 0x5a5a     Default     0x5a4c6              674    14   appstoreagent: [com.apple.appstored:Library] [A95D57D7] Completed with 1 result: <ASDApp: 0xc932a8780>: {bundleID = com.our.app; completedUnitCount = 600; path = /Applications/OurApp.app; installed = 0} 2025-12-02 22:10:32.027304-0800 0x5ae5     Default     0x5a4c7              674    14   appstoreagent: [com.apple.appstored:Library] [BEB5F2FD] Completed with 1 result: <ASDApp: 0xc932a8780>: {bundleID = com.our.app; completedUnitCount = 600; path = /Applications/OurApp.app; installed = 0} 2025-12-02 22:10:36.542321-0800 0x5b81     Default     0x5a4c8              674    14   appstoreagent: [com.apple.appstored:Library] [185B9DD6] Completed with 1 result: <ASDApp: 0xc932a8780>: {bundleID = com.our.app; completedUnitCount = 600; path = /Applications/OurApp.app; installed = 0} The line "Terminating with context" seems suspicious. This line is not seen on MacOS 15, only MacOS 26. Is this documented behavior? If so, how can we handle this?
7
0
189
3d
ExtensionFoundation/ExtensionKit across app boundary
Hi there, I'm trying to work on an architecture where one app exposes an API (Extension Host) that other apps can plugin to. I've been reading all I can from the docs and whatever I can find online. It seemed like iOS26 added the ability to do such a thing (at least in early builds). Is that the case? Has the functionality been walked back such that extensions can only be loaded in iOS from within the single app bundle? My use case is the following: I'm working on an agent app that desires to have 3rd party developers add functionality (think how MCP servers add functionality to LLMs). The 3rd party plugins would be provided in their own app bundles vetted by the AppStore review team, of course, and would only provide hooks, basically, the main app can use to execute functions or get state. This is the best thread I found on the topic, and the subtext is that it needs to be in the same bundle. https://developer.apple.com/forums/thread/803896?answerId=865314022#865314022 Let's say for the moment that this isn't possible using ExtensionKit. What's the best way to achieve this? Our current best alternative idea is a hidded WebKit window that runs JS/WASM but that's so hackish. Please let me know, thanks!
3
0
114
3d
application(_:didFinishLaunchingWithOptions:) not called on MDM iPads after overnight idle — app resumes without cold start
We are seeing a strange lifecycle issue on multiple MDM-managed iPads where application(_:didFinishLaunchingWithOptions:) is not called after the device is idle overnight. Even if we terminate the app manually via the app switcher, the next morning the system does not perform a cold launch. Instead, the app resumes directly in: applicationDidBecomeActive(_:) This causes all initialization logic that depends on didFinishLaunching to be completely skipped. This behavior is consistent across four different supervised MDM devices. Environment Devices: iPads enrolled in MDM (supervised) iOS version: 18.3 Xcode: 16.4 macOS: Sequoia 15.7.2 App type: Standard UIKit iOS app App: Salux Audiometer (App Store app) Expected Behavior If the app was terminated manually using the app switcher, the next launch should: Start a new process Trigger application(_:didFinishLaunchingWithOptions:) Follow the normal cold-start lifecycle Actual Behavior After leaving the iPad idle overnight (8–12 hours): The next launch skips didFinishLaunching The app resumes directly in applicationDidBecomeActive No new process is started App behaves as if it had been suspended, even though it was manually terminated Logs (Relevant Extracts) Day 1 — Normal cold launch [12:06:44.152 PM] PROCESS_STARTED [12:06:44.214 PM] DID_FINISH_LAUNCHING_START launchOptions=[] [12:06:44.448 PM] DID_FINISH_LAUNCHING_END We then used the app and terminated it via app switcher. Day 2 — Unexpected resume without cold start [12:57:49.328 PM] APP_DID_BECOME_ACTIVE No PROCESS_STARTED No didFinishLaunching No cold-start logs This means the OS resumed the app from a previous state that should not exist. Reproducible Steps Use an MDM-enrolled iPad. Launch the app normally. Terminate it manually via the multitasking app switcher. Leave the device idle overnight (8–12 hours). Launch the app the next morning. Observe that: didFinishLaunching does not fire applicationDidBecomeActive fires directly Questions for Apple Engineers / Community Is this expected behavior on MDM-supervised devices in iOS 18? Are there any known OS-level changes where terminated apps may be revived from disk/memory? Could MDM restrictions or background restoration policies override app termination? How can we ensure that our app always performs a clean initialization when launched after a long idle period? Additional Information We have full logs from four separate MDM iPads showing identical behavior. Happy to share a minimal reproducible sample if required.
1
0
36
3d
ExtensionKit and iOS 26
It looks like ExtensionKit (and ExtensionFoundation) is fully available on iOS 26 but there is no mention about this in WWDC. From my testing, it seems as of beta 1, ExtensionKit allows the app from one dev team to launch extension provided by another dev team. Before we start building on this, can someone from Apple help confirm this is the intentional behavior and not just beta 1 thing?
3
4
249
4d
BGContinuedProcessingTask expiring unpredictably
I've adopted the new BGContinuedProcessingTask in iOS 26, and it has mostly been working well in internal testing. However, in production I'm getting reports of the tasks failing when the app is put into the background. A bit of info on what I'm doing: I need to download a large amount of data (around 250 files) and process these files as they come down. The size of the files can vary: for some tasks each file might be around 10MB. For other tasks, the files might be 40MB. The processing is relatively lightweight, but the volume of data means the task can potentially take over an hour on slower internet connections (up to 10GB of data). I set the totalUnitCount based on the number of files to be downloaded, and I increment completedUnitCount each time a file is completed. After some experimentation, I've found that smaller tasks (e.g. 3GB, 10MB per file) seem to be okay, but larger tasks (e.g. 10GB, 40MB per file) seem to fail, usually just a few seconds after the task is backgrounded (and without even opening any other apps). I think I've even observed a case where the task expired while the app was foregrounded! I'm trying to understand what the rules are with BGContinuedProcessingTask and I can see at least four possibilities that might be relevant: Is it necessary to provide progress updates at some minimum rate? For my larger tasks, where each file is ~40MB, there might be 20 or 30 seconds between progress updates. Does this make it more likely that the task will be expired? For larger tasks, the total time to complete can be 60–90 mins on slower internet connections. Is there some maximum amount of time the task can run for? Does the system attempt some kind of estimate of the overall time to complete and expire the task on that basis? The processing on each file is relatively lightweight, so most of the time the async stream is awaiting the next file to come down. Does the OS monitor the intensity of workload and suspend the task if it appears to be idle? I've noticed that the task UI sometimes displays a message, something along the lines of "Do you want to continue this task?" with a "Continue" and "Stop" option. What happens if the user simply ignores or doesn't see this message? Even if I tap "Continue" the task still seems to fail sometimes. I've read the docs and watched the WWDC video, but there's not a whole lot of information on the specific issues I mention above. It would be great to get some clarity on this, and I'd also appreciate any advice on alternative ways I could approach my specific use case.
7
0
269
1w
BGContinuedProcessingTask does not respect fractionCompleted to keep alive
I posted here https://developer.apple.com/forums/thread/805554?page=1#867766022 but posting again for visibility (and let me know how I can file a bug) There was a response in that thread that said you could use the childProgress system to help updating progresses to keep the backgroundTask alive. What I've found is that using childProgresses results in more terminations than if you just updated the progress directly. Here is my setups to test this A BGContinuedProcessingTask that uses URLSessions to upload, and registers the task.progress with the Urlsession Progress Same, but the task.progress gets updated via a UrlSession Callback The second is MUCH more stable out in the field in cellular settings, the first fails extremely frequently. My suspicion is that in the documentation here https://developer.apple.com/documentation/foundation/progress#Reporting-Progress-for-Multiple-Operations it explicitly states The completedUnitCount property for a containing progress object only updates when the suboperation is 100% complete. The fractionCompleted property for a containing progress object updates continuously as work progresses for all suboperations. I wonder if BGContinuedProcessingTask is only looking at completedUnitCount for progress, and not fractionCompleted? In either case, I would love to use the childProgresses because there are bugs with retries by updating the progress manually, so would love some help resolving this, Thanks!
2
0
52
1w
How is BGContinuedProcessingTask intended to be used?
Hello, I'm trying to adopt the new BGContinuedProcessingTask API, but I'm having a little trouble imagining how the API authors intended it be used. I saw the WWDC talk, but it lacked higher-level details about how to integrate this API, and I can't find a sample project. I notice that we can list wildcard background task identifiers in our Info.plist files now, and it appears this is to be used with continued tasks - a user might start one video encoding, then while it is ongoing, enqueue another one from the same app, and these tasks would have identifiers such as "MyApp.VideoEncoding.ABCD" and "MyApp.VideoEncoding.EFGH" to distinguish them. When it comes to implementing this, is the expectation that we: a) Register a single handler for the wildcard pattern, which then figures out how to fulfil each request from the identifier of the passed-in task instance? Or b) Register a unique handler for each instance of the wildcard pattern? Since you can't unregister handlers, any resources captured by the handler would be leaked, so you'd need to make sure you only register immediately before submission - in other words register + submit should always be called as a pair. Of course, I'd like to design my application to use this API as the authors intended it be used, but I'm just not entirely sure what that is. When I try to register a single handler for a wildcard pattern, the system rejects it at runtime (while allowing registrations for each instance of the pattern, indicating that at least my Info.plist is configured correctly). That points towards option B. If it is option B, it's potentially worth calling that out in documentation - or even better, perhaps introduce a new call just for BGContinuedProcessingTask instead of the separate register + submit calls? Thanks for your insight. K Aside: Also, it would be really nice if the handler closure would be async. Currently if you need to await on something, you need to launch an unstructured Task, but that causes issues since BGContinuedProcessingTask is not Sendable, so you can't pass it in to that Task to do things like update the title or mark the BGTask as complete.
12
0
435
1w
Some questions about how to use the Background Assets capability on iOS
Regarding the Background Assets capability on iOS: In the install scenario, resources defined as the "install" type are incorporated into the App Store download progress. Do resources of the "update" type in the update scenario also get incorporated into the App Store download progress in the same way? If an exception occurs during the download of install-type resources and the download cannot proceed further, will the system no longer actively block users from launching the app and instead enable the launch button? Currently, if a user has enabled automatic updates on their device, after the app is updated and released on the App Store, will the Background Assets download start immediately once the automatic update completes? Or does Background Assets have its own built-in scheduling logic that prevents it from running concurrently with the automatic update?
1
0
47
1w
Feature Request: Reason for taskExpiration for BGContinuedProcessingTask
I've tuned my task to be decently resilient, but I found a few issues that caused it to expire regularly. excessive CPU usage -> I'm actually running it behind ReactNative, and I found an issue where I was still updating ReactNative and thus it was keeping it alive the entire time the task was running. Removing this update helped improve stability not updating progress frequently enough ( see https://developer.apple.com/forums/thread/809182?page=1#868247022) My feature request is, would it be possible to get a reason the task was expired in task.expirationHandler? That would be helpful for both the user and for debugging why the task was expired. Thanks!
1
0
40
1w
Behavior of BGContinuedProcessingTask on Failure
Hi there, First thanks for all the work on BGContinuedProcessingTask! It looks really promising. I have a question / issue around the behavior when a BGContinuedProcessingTask expires. Here is my setup. I have an app who's responsible for uploading large files in the field (AKA wifi is not expected) For a given file, it can likely fail due to network conditions I'm using Multipart upload though so I can retry a file to pick up where it left off. I use one taskIdentifier per file, and when the file fails, I can retry the task and have it continue where it left off (I am reusing the taskIdentifier here for retries, let me know if I shouldn't be doing that) Here is the behavior I am seeing I start an upload, it seems to be uploading normally I turn on airplane mode to simulate expiration of the task the task fails as expected after ~30 seconds, and I see the failure in my home screen. I have callbacks in the task to put my app in the proper state on expiration / failure I turn back on airplane mode and I retry the task, the way I do this is I do NOT re-register, I simply re-submit the task with the same TaskIdentifier. What I would have expected is that the failure task is REPLACED with the new task and new progress. Instead what I see is TWO ContinuedBackgroundProcessingTasks, one in the failure state and one in progress. My question is How can I make retries reuse the same task notification item? OR if that's not possible, how do I programmatically clear the task failure? I've tried cancelTask but that doesn't seem to clear it.
3
1
182
1w
Running processing task for data upload together with state restoration
Hi All, In continuation of this thread https://developer.apple.com/forums/thread/804439 I want to perform data upload after getting it from the BLE device. As state restoration wake should not deal with data upload i though of using a processing task to perform the data upload. So the flow will be something like: Connect to device -> listen to notification -> go to background -> wake from notification -> handle data download from ble device -> register processing task for data upload -> hopefully get the data uploaded From reading about processing task i understand that the task execution is completely handled by the OS and depends on user behaviour and app usage. I even saw that if the user is not using the app for a while, the OS might not even perfoirm the task. So my quesiton is: does state restoration wakeup and perfroming data dowloads in the backgound considered app usage that will increase the likeluhood the task will get execution time? Can we rely on this for a scenario that the user opens the app for the first time, register, onboard for ble, connect to devie and then put it in the background for days or weeks and only relying on state restoration and processing tasks to do their thing? Sorry for the long read and appreciate your support! Shimon
1
0
38
1w
NotificationCenter.notifications(named:) appears to buffer internally and can drop notifications, but is this documented anywhere?
I've experimentally seen that the notifications(named:) API of NotificationCenter appears to buffer observed notifications internally. In local testing it appears to be limited to 8 messages. I've been unable to find any documentation of this fact, and the behavior seems like it could lead to software bugs if code is not expecting notifications to potentially be dropped. Is this behavior expected and documented somewhere? Here is a sample program demonstrating the behavioral difference between the Combine and AsyncSequence-based notification observations: @Test nonisolated func testNotificationRace() async throws { let testName = Notification.Name("TestNotification") let notificationCount = 100 var observedAsyncIDs = [Int]() var observedCombineIDs = [Int]() let subscribe = Task { @MainActor in print("setting up observer...") let token = NotificationCenter.default.publisher(for: testName) .sink { value in let id = value.userInfo?["id"] as! Int observedCombineIDs.append(id) print("🚜 observed note with id: \(id)") } defer { extendLifetime(token) } for await note in NotificationCenter.default.notifications(named: testName) { let id: Int = note.userInfo?["id"] as! Int print("🚰 observed note with id: \(id)") observedAsyncIDs.append(id) if id == notificationCount { break } } } let post = Task { @MainActor in for i in 1...notificationCount { NotificationCenter.default.post( name: testName, object: nil, userInfo: ["id": i] ) } } _ = await (post.value, subscribe.value) #expect(observedAsyncIDs.count == notificationCount) // 🛑 Expectation failed: (observedAsyncIDs.count → 8) == (notificationCount → 100) #expect(observedCombineIDs == Array(1...notificationCount)) print("done") }
2
0
159
1w
BGContinuedProcessingTask code pauses when device is locked
I have been experimenting with the BGContinuedProcessingTask API recently (and published sample code for it https://github.com/infinitepower18/BGContinuedProcessingTaskDemo) I have noticed that if I lock the phone, the code that runs as part of the task stops executing. My sample code simply updates the progress each second until it gets to 100, so it should be completed in 1 minute 40 seconds. However, after locking the phone and checking the lock screen a few seconds later the progress indicator was in the same position as before I locked it. If I leave the phone locked for several minutes and check the lock screen the live activity says "Task failed". I haven't seen anything in the documentation regarding execution of tasks while the phone is locked. So I'm a bit confused if I encountered an iOS bug here?
9
0
332
1w
Flutter library that basically makes a call every "x" minutes if the app is in the background.
Hi everyone, could you help us? We implemented a Flutter library that basically makes a call every x minutes if the app is in the background, but when I generate the version via TestFlight for testing, it doesn't work. Can you help us understand why? Below is a more detailed technical description. Apple Developer Technical Support Request Subject: BGTaskScheduler / Background Tasks Not Executing in TestFlight - Flutter App with workmanager Plugin Issue Summary Background tasks scheduled using BGTaskScheduler are not executing when the app is distributed via TestFlight. The same implementation works correctly when running the app locally via USB/Xcode debugging. We are developing a Flutter application that needs to perform periodic API calls when the app is in the background. We have followed all documentation and implemented the required configurations, but background tasks are not being executed in the TestFlight build. App Information Field Value App Version 3.1.15 (Build 311) iOS Minimum Deployment Target iOS 15.0 Framework Flutter Flutter SDK Version ^3.7.2 Technical Environment Flutter Dependencies (Background Task Related) Package Version Purpose workmanager ^0.9.0+3 Main background task scheduler (uses BGTaskScheduler on iOS 13+) flutter_background_service ^5.0.5 Background service management flutter_background_service_android ^6.2.4 Android-specific background service flutter_local_notifications ^19.4.2 Local notifications for background alerts timezone ^0.10.0 Timezone support for scheduling Other Relevant Flutter Dependencies Package Version firebase_core 4.0.0 firebase_messaging (via native Podfile) sfmc (Salesforce Marketing Cloud) ^9.0.0 geolocator ^14.0.0 permission_handler ^12.0.0+1 Info.plist Configuration We have added the following configurations to Info.plist: UIBackgroundModes <key>UIBackgroundModes</key> <array> <string>location</string> <string>remote-notification</string> <string>processing</string> </array> ### BGTaskSchedulerPermittedIdentifiers ```xml <key>BGTaskSchedulerPermittedIdentifiers</key> <array> <string>br.com.unidas.apprac.ios.workmanager.carrinho_api_task</string> <string>br.com.unidas.apprac.ios.workmanager</string> <string>be.tramckrijter.workmanager.BackgroundTask</string> </array> **Note:** We included multiple identifier formats as recommended by the `workmanager` Flutter plugin documentation: 1. `{bundleId}.ios.workmanager.{taskName}` - Custom task identifier 2. `{bundleId}.ios.workmanager` - Default workmanager identifier 3. `be.tramckrijter.workmanager.BackgroundTask` - Plugin's default identifier (as per plugin documentation) ## AppDelegate.swift Configuration We have configured the `AppDelegate.swift` with the following background processing setup: ```swift // In application(_:didFinishLaunchingWithOptions:) // Configuration to enable background processing via WorkManager // The "processing" mode in UIBackgroundModes allows WorkManager to use BGTaskScheduler (iOS 13+) // This is required to execute scheduled tasks in background (e.g., API calls) // Note: User still needs to have Background App Refresh enabled in iOS settings if UIApplication.shared.backgroundRefreshStatus == .available { // Allows iOS system to schedule background tasks with minimum interval UIApplication.shared.setMinimumBackgroundFetchInterval(UIApplication.backgroundFetchIntervalMinimum) } ## WorkManager Implementation (Dart/Flutter) ### Initialization ```dart /// Initializes WorkManager static Future<void> initialize() async { await Workmanager().initialize(callbackDispatcher, isInDebugMode: false); print('WorkManagerService: WorkManager initialized'); } ### Task Registration /// Schedules API execution after a specific delay ## Observed Behavior ### Works (Debug/USB Connection) - When running the app via Xcode/USB debugging - Background tasks are scheduled and executed as expected - API calls are made successfully when the app is backgrounded ### Does NOT Work (TestFlight) - When the app is distributed via TestFlight - Background tasks appear to be scheduled (no errors in code) - Tasks are **never executed** when the app is in background - We have tested with: - Background App Refresh enabled in iOS Settings - App used frequently - Device connected to WiFi and charging - Waited for extended periods (hours) ## Possible heart points 1. **Are there any additional configurations required for `BGTaskScheduler` to work in TestFlight/Production builds that are not required for debug builds?** 2. **Is the identifier format correct?** We are using: `br.com.unidas.apprac.ios.workmanager.carrinho_api_task` - Should it match exactly with the task name registered in code? 3. **Are there any known issues with Flutter's `workmanager` plugin and iOS BGTaskScheduler in production environments?** 4. **Is there any way to verify through logs or system diagnostics if the background tasks are being rejected by the system?** 5. **Could there be any conflict between our other background modes (`location`, `remote-notification`) and `processing`?** 6. **Does the Salesforce Marketing Cloud SDK (SFMC) interfere with BGTaskScheduler operations?** ## Additional Context - We have verified that `Background App Refresh` is enabled for our app in iOS Settings - The app has proper entitlements for push notifications and location services - Firebase, SFMC (Salesforce Marketing Cloud), and other SDKs are properly configured - The issue is **only** present in TestFlight builds, not in debug/USB-connected builds ## References - [Apple Documentation - BGTaskScheduler](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler) - [Apple Documentation - Choosing Background Strategies](https://developer.apple.com/documentation/backgroundtasks/choosing_background_strategies_for_your_app) Thank you
2
0
44
1w
LaunchAgent (Mac) as peripheral doesn't show a pairing request.
The same code built in a regular Mac app (with UI) does get paired. The characteristic properties are [.read, .write, .notify, .notifyEncryptionRequired] The characteristic permissions are [.readEncryptionRequired, .writeEncryptionRequired] My service is primary. In the iOS app (central) I try to read the characteristic, but an error is reported: Error code: 5, Description: Authentication is insufficient.
3
0
72
1w