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

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!
2
0
248
Dec ’25
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.
7
0
403
Jan ’26
Can an app launch automatically after watchOS restarts?
Regarding App Update Synchronization During Workout Mode: My watchOS app has workout mode enabled. When I update the app from the App Store on my iPhone while a workout session is active on my Apple Watch, the update does not sync to the watch. Why does this happen, and when can I expect the watch app to be updated? Regarding Automatic App Launch After a Prolonged Shutdown: I would like my watchOS app to launch automatically on my Apple Watch after it has been powered off for an extended period and then turned back on. Is this functionality possible to implement? If not, please provide a definitive answer regarding this capability.
1
0
191
Jan ’26
nonisolated Execution Differences Before and After Xcode 26.2
I have an older project that was created before Xcode 26.2. In Xcode versions prior to 26.2, there was no Swift Compiler – Concurrency build setting. With those older versions, the following behavior occurs: a nonisolated function executes off the main thread. class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() run() } private func run() { Task { await runInMainThread() } } func runInMainThread() async { print(">>>> IN runInMainThread(), Thread.isMainThread \(Thread.isMainThread)") await runInBackgroundThread() } private nonisolated func runInBackgroundThread() async { print(">>>> IN runInBackgroundThread(), Thread.isMainThread \(Thread.isMainThread)") } } Output: >>>> IN runInMainThread(), Thread.isMainThread true >>>> IN runInBackgroundThread(), Thread.isMainThread false However, starting with Xcode 26.2, Apple introduced the Swift Compiler – Concurrency settings. When running the same code with the default configuration: Approachable Concurrency = Yes Default Actor Isolation = MainActor This is the output Output: >>>> IN runInMainThread(), Thread.isMainThread true >>>> IN runInBackgroundThread(), Thread.isMainThread true the nonisolated function now executes on the main thread. This raises the following questions: What is the correct Swift Compiler – Concurrency configuration if I want a nonisolated function to run off the main thread? Is nonisolated still an appropriate way to ensure code runs on a background thread?
3
0
251
Feb ’26
Capturing screen buffer at macOS Login Window with ScreenCaptureKit and PrivilegedHelper
I am developing a remote support tool for macOS. While we have successfully implemented a Privileged Helper Tool and LaunchDaemon architecture that works within an active Aqua session, we have observed a total failure to capture the screen buffer or receive input at the macOS Login Window. Our observation of competitor software (AnyDesk, TeamViewer) shows they maintain graphical continuity through logout/restart. We are seeking the official architectural path to replicate this system-level access. Current Technical Implementation Architecture: A root-level LaunchDaemon manages the persistent network connection. A PrivilegedHelperTool (installed in /Library/PrivilegedHelperTools/) is used for elevated tasks. Environment: Tested on macOS 14.x (Sonoma) and macOS 15.x (Sequoia) on Apple Silicon. Capture Methods: We have implemented ScreenCaptureKit (SCK) as the primary engine and CGDisplayCreateImage as a fallback. Binary Status: All components are signed with a Developer ID and have been successfully Notarized. Observed Behavior & Blockers The "Aqua" Success: Within a logged-in user session, our CGI correctly identifies Display IDs and initializes the capture stream. Remote control is fully functional. The "Pre-Login" Failure: When the Mac is at the Login Window (no user logged in), the following occurs: The Daemon remains active, but the screen capture buffer returns NULL or an empty frame. ScreenCaptureKit fails to initialize, citing a lack of graphical context. No TCC (Transparency, Consent, and Control) prompt can appear because no user session exists. The "Bootstrap" Observation: We have identified that the loginwindow process exists in a restricted Mach bootstrap namespace that our Daemon (running in the System domain) cannot natively bridge. Comparative Analysis (Competitor Benchmarking) We have analyzed established remote desktop solutions like AnyDesk and Jump Desktop to understand their success at the login screen. Our findings suggest: Dual-Context Execution: They appear to use a Global LaunchAgent with LimitLoadToSessionType = ["LoginWindow"]. This allows a child process to run as root inside the login window’s graphical domain. Specialized Entitlements: These apps have migrated to the com.apple.developer.persistent-content-capture entitlement. This restricted capability allows them to bypass the weekly/monthly TCC re-authorization prompts and function in unattended scenarios where a user cannot click "Allow." Questions Entitlement Requirement: Is the persistent-content-capture entitlement the only supported way for a third-party app to capture the LoginWindow buffer without manual user intervention? LaunchAgent Strategy: To gain a graphical context at the login screen, is it recommended to load a specialized agent into the loginwindow domain via launchctl bootstrap loginwindow ...? ScreenCaptureKit vs. Legacy: Does ScreenCaptureKit officially support the LoginWindow session, or does it require an active Aqua session to initialize? MDM Bypass: For Enterprise environments, can a Privacy Preferences Policy Control (PPPC) payload grant "Screen Recording" to a non-entitled Daemon specifically for the login window context?
1
0
482
Jan ’26
Where did I screw up trying concurrency?
I tried making a concurrency-safe data queue. It was going well, until memory check tests crashed. It's part of an unadvertised git project. Its location is: https://github.com/CTMacUser/SynchronizedQueue/commit/84a476e8f719506cbd4cc6ef513313e4e489cae3 It's the blocked-off method "`memorySafetyReferenceTypes'" in "SynchronizedQueueTests.swift." Note that the file and its tests were originally AI slop.
2
0
295
Feb ’26
Inter-app Communication with Third Party SDK
I’ve built an app that connects via Bluetooth to a device. The device sends up, down, left and right commands. I want to build an SDK for other third party developers to use so that whenever a third party app with the SDK opens, if we press a button on the device, my app which captures the button press should be able to forward the event to the third party app. I want to achieve this with the lowest latency possible so that I can enable a variety of use cases like simple games and interactions within other apps. What would be the best way for me to achieve this as part of my SDK and my app?
3
0
279
Feb ’26
Trouble creating an XPC service for out-of-process rendering
I'm working on an editor for Bevy games and wanted the following workflow: Launch the game process Host a Metal view for the game's render target Use an XPC service to transfer an MTLSharedTextureHandle Keep the connection for editor/game communication and hot reload As such I created the following editor service: public let XPCEditorServiceName = "org.bevy.editor" public enum XPCEditorMessage: Codable { case ping } public enum XPCEditorReply: Codable { case pong } extension XPCListener { static let bevy = try! XPCListener(service: XPCEditorServiceName) { request in request.accept(XPCEditorService.init) } } struct XPCEditorService: XPCPeerHandler { let session: XPCSession private func handle(_ message: XPCEditorMessage) -> XPCEditorReply? { switch message { case .ping: return .pong } } func handleIncomingRequest(_ message: XPCReceivedMessage) -> (any Encodable)? { do { return handle(try message.decode()) } catch { return nil } } func handleCancellation(error: XPCRichError) { print(error) } } and I initialize it in my app's App initializer: // Launch the XPC service print(XPCListener.bevy) I wanted to test this using an executable target with the following main.swift: let session = try XPCSession(xpcService: XPCEditorServiceName) let response: XPCEditorReply = try session.sendSync(XPCEditorMessage.ping) print("Connected to editor!") The editor prints Listener<org.bevy.editor>(Active) but the game fails with Underlying connection was invalidated. Reason: Connection init failed at lookup with error 3 - No such process What am I doing wrong? PS. Would also appreciate an example of sending & rendering the MTLSharedTextureHandle both in editor & game.
2
0
142
Feb ’26
Migrating away from SMJobBless
I have migrated my code to use SMAppService but am running into trouble deleting the old SMJobBless launchd registration using launchd remove. I am invoking this from a root shell when I detect the daemon and associated plist still exist, then also deleting those files. The remove seems to work (i.e. no errors returned) but launchd list shows the service is registered, with a status code of 28 I am using the same label for SMAppService as previously and suspect this is the reason for the problem. However, I am reluctant to change the label as there will a lot of code changes to do this. If I quit my application, disable the background job in System Settings and run sudo launchd remove in the Terminal then it is removed and my application runs as expected once the background job is re-enabled. Alternatively, a reboot seems to get things going. Any suggestions on to how I could do this more effectively welcome.
2
0
150
Mar ’26
Unix Domain Socket path for IPC between LaunchDaemon and LaunchAgent
Hello, I am working on a cross-platform application where IPC between a LaunchDaemon and a LaunchAgent is implemented via Unix domain sockets. On macOS, the socket path length is restricted to 104 characters. What is the Apple-recommended directory for these sockets to ensure the path remains under the limit while allowing a non-sandboxed agent to communicate with a root daemon? Standard paths like $TMPDIR are often too long for this purpose. Thank you in advance!
4
0
221
Mar ’26
Clarification on concurrency guarantees for shared data between App and Widget extensions
Hi, I’m looking for clarification on what concurrency and consistency guarantees Apple provides when multiple targets (main app + Widget extensions) access shared storage. Specifically: 1. UserDefaults (App Group / suiteName:) • If multiple processes (app + multiple widget instances) read and write the same shared UserDefaults, what guarantees are provided? • Is access serialized internally to prevent corruption? • Are read–modify–write operations safe across processes, or can lost updates occur? 2. Core Data (shared SQLite store in App Group container) • Is it officially supported for multiple processes to open and write to the same Core Data SQLite store? • Are there recommended configurations (e.g. WAL mode) for safe multi-process access? • Is Apple’s recommendation to have a single writer process? 3. FileManager (shared container files) • If two processes write to the same file in an App Group container, what guarantees are provided by the system? • Is atomic replaceItemAt the recommended pattern for safe cross-process updates? Additionally: • Do multiple widget instances count as separate processes with respect to these guarantees? • Is there official guidance on best practices for shared persistence between app and widget extensions? I want to ensure I’m following the correct architecture and not relying on undefined behavior. Thanks.
1
0
175
Mar ’26
How to launch a sandboxed process as a standalone application?
Hello, I have an application that needs to be published to the App Store. This application consists of two processes, A and B, where B is a child process of A. I found that if process B needs to be launched as a child process of A in sandbox mode, it is necessary to set the following keys in the entitlements.plist file: <key>com.apple.security.app-sandbox</key><true/><key>com.apple.security.inherit</key><true/> However, after setting these keys, process B can no longer be launched directly. This issue is particularly prominent because process B has a window and a Dock icon — in this case, if the user pins the Dock icon, they will be unable to launch process B. Could you please advise on a solution to this problem?
1
0
155
Mar ’26
BGProcessingTask expirationHandler — No way to distinguish expiration reason
The expirationHandler on BGProcessingTask is a () -> Void closure. It provides no information about why it was called. In my testing, all of the following trigger the same handler: Time expiration Resource pressure (CPU, memory, battery) Not reporting progress User tapping "Stop" on the Live Activity There is no way for the app to tell these apart. Questions: Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires." Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions? Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently this is impossible. Environment: iOS 26, physical device
1
0
105
Mar ’26
BGProcessingTask expirationHandler — No way to distinguish expiration reason
The expirationHandler on BGProcessingTask is a () -> Void closure. It provides no information about why it was called. In my testing, all of the following trigger the same handler: Time expiration Resource pressure (CPU, memory, battery) Not reporting progress User tapping "Stop" on the Live Activity There is no way for the app to tell these apart. Questions: Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires." Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions? Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently this is impossible. Environment: iOS 26, physical device
5
0
199
4w
Securing XPC Daemon Communication from Authorization Plugin
I'm working on securing communication between an Authorization Plugin and an XPC daemon, and I’d appreciate some guidance on best practices and troubleshooting. The current design which, I’ve implemented a custom Authorization Plugin for step-up authentication, which is loaded by Authorization Services at the loginwindow (inside SecurityAgent). This plugin acts as an XPC client and connects to a custom XPC daemon. Setup Details 1. XPC Daemon Runs as root (LaunchDaemon) Not sandboxed (my understanding is that root daemons typically don’t run sandboxed—please correct me if this is wrong) Mach service: com.roboInc.AuthXpcDaemon Bundle identifier: com.roboInc.OfflineAuthXpcDaemon 2. Authorization Plugin Bundle identifier: com.roboInc.AuthPlugin Loaded by SecurityAgent during login 3. Code Signing Both plugin and daemon are signed using a development certificate What I’m Trying to Achieve I want to secure the XPC communication so that: The daemon only accepts connections from trusted clients The plugin only connects to the legitimate daemon Communication is protected against unauthorized access The Issue I'm facing I attempted to validate code signatures using: SecRequirementCreateWithString SecCodeCopyGuestWithAttributes SecCodeCheckValidity However, validation consistently fails with: -67050 (errSecCSReqFailed) Could you please help here What is the recommended way to securely authenticate an Authorization Plugin (running inside SecurityAgent) to a privileged XPC daemon? Since the plugin runs inside SecurityAgent, how can the daemon reliably distinguish my plugin from other plugins? What is the correct approach to building a SecRequirement in this scenario? Any guidance, examples, or pointers would be greatly appreciated. Thanks in advance!
6
0
281
2w
FIFinderSync Extension fails to load on FIFinderSync Extension fails to load on macOS 26.3.1 (a) (25D771280a)
(! status in pluginkit, FinderSyncExtensionHost process missing) macOS Version: 26.3.1 Beta (25D771280a) Xcode Version: 16.3 (17C529) Steps to reproduce: Create a Finder Sync Extension project Build and install to /Applications Enable in System Settings → Extensions → Finder Extensions Extension shows ! in pluginkit output FinderSyncExtensionHost process never starts Context menu never appears in Finder Expected: Extension loads and context menu appears Actual: Extension marked with ! in pluginkit, no process launched pluginkit output: ! com.github.astronautJack.EasyNewFile.EasyNewFileExtension(1.0)
1
0
94
3w
How to debug a Launch Daemon that requires an App Group provisioning profile for XPC communication
Hello, I am developing a macOS Launch Daemon (packaged as a bundle) that acts as an XPC server. For debugging purposes, I am trying to run the daemon's executable directly from the terminal via sudo ./mydaemon.app/Contents/MacOS/myexecutable. Initially, I added the com.apple.security.application-groups entitlement to the daemon. However, when starting the process, it failed to create the XPC service with the following errors: Unsatisfied entitlements: com.apple.security.application-groups Soft-restriction provisioning profile validation failure: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=, unsatisfiedEntitlements=, NSLocalizedDescription=No matching profile found} listener failed to activate: xpc_error=[1: Operation not permitted] To resolve the profile validation failure, I registered a new App Group in the Apple Developer Portal, generated a new provisioning profile for the daemon that includes this group, and embedded it into the bundle (Contents/embedded.provisionprofile). Now, the previous profile error is gone, but I am getting a new identity conflict error, and the XPC listener still fails: Two equal instances have unequal identities. <anon<myproc_name>(501) pid=2818 AUID=501> and <anon<myproc_name>(501)(262) pid=2818 AUID=262> listener failed to activate: xpc_error=[1: Operation not permitted] My questions are: What exactly causes the Two equal instances have unequal identities error? I noticed the Audit UID difference (AUID=501 vs AUID=262). Why does NSXPCListener still fail with Operation not permitted? What is the recommended workflow for debugging a Launch Daemon that requires an App Group provisioning profile for XPC communication? Thank you in advance!
2
0
99
1w
App Terminated with 0x8BADF00D: Main Thread Blocked During Back-to-Back Messaging
Hello, I'm experiencing an issue with my app where it's being terminated by the system with a watchdog violation during back-to-back messaging operations. I've analyzed the crash logs but would appreciate additional insights on optimizing my approach. I'd appreciate any insights on how to resolve this problem. Crash Details: Exception Type: EXC_CRASH (SIGKILL) Termination Reason: FRONTBOARD with code 0x8BADF00D Error: "scene-update watchdog transgression: app exhausted real time allowance of 10.00 seconds" Reproduction Steps: User A initiates back-to-back messages to other User User A's UI becomes unresponsive and eventually the app crashes. Stack Trace Analysis: The crash occurs on the main thread, which appears to be blocked waiting for a condition in the keyboard handling system. The thread is stuck in [UIKeyboardTaskQueue _lockWhenReadyForMainThread] and related methods, suggesting an issue with keyboard-related operations during the messaging process. Crash Tag Exception Type: EXC_CRASH (SIGKILL) Exception Codes: 0x0000000000000000, 0x0000000000000000 Termination Reason: FRONTBOARD 2343432205 <RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: app<com.msikodiak.eptt(AD934F8A-DF57-4B75-BE73-8CF1A9A8F856)>:301 exhausted real (wall clock) time allowance of 10.00 seconds ProcessVisibility: Foreground ProcessState: Running WatchdogEvent: scene-update WatchdogVisibility: Background WatchdogCPUStatistics: ( "Elapsed total CPU time (seconds): 6.390 (user 3.640, system 2.750), 11% CPU", "Elapsed application CPU time (seconds): 0.020, 0% CPU" ) ThermalInfo: ( "Thermal Level: 0", "Thermal State: nominal" ) reportType:CrashLog maxTerminationResistance:Interactive> Triggered by Thread: 0 Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libsystem_kernel.dylib 0x1e773d438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x2210bc328 _pthread_cond_wait + 1028 2 Foundation 0x1957d8a64 -[NSCondition waitUntilDate:] + 132 3 Foundation 0x1957d8888 -[NSConditionLock lockWhenCondition:beforeDate:] + 80 4 UIKitCore 0x1998f1238 -[UIKeyboardTaskQueue _lockWhenReadyForMainThread] + 456 5 UIKitCore 0x19a3d775c __59-[UIKeyboardImpl updateAutocorrectPrompt:executionContext:]_block_invoke_9 + 28 6 UIKitCore 0x19986b084 -[UIKeyboardTaskQueue lockWhenReadyForMainThread] + 168 7 UIKitCore 0x19a3f2994 -[UIKeyboardTaskQueue waitUntilTaskIsFinished:] + 148 8 UIKitCore 0x19a3f2ac4 -[UIKeyboardTaskQueue performSingleTask:breadcrumb:] + 132 9 UIKitCore 0x199e2f7e4 -[_UIKeyboardStateManager updateForChangedSelection] + 144 10 UIKitCore 0x199e24200 -[_UIKeyboardStateManager invalidateTextEntryContextForTextInput:] + 92 11 WebKit 0x1ad52fa54 WebKit::PageClientImpl::didProgrammaticallyClearFocusedElement(WebCore::ElementContext&&) + 40 12 WebKit 0x1ad55adcc WebKit::WebPageProxy::didProgrammaticallyClearFocusedElement(WebCore::ElementContext&&) + 136 13 WebKit 0x1acec74e8 WebKit::WebPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 18604 14 WebKit 0x1acd21184 IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 236 15 WebKit 0x1ace449b8 WebKit::WebProcessProxy::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 40 16 WebKit 0x1ace44228 WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 1764 17 WebKit 0x1acd1e904 IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 268 18 WebKit 0x1acd1e478 IPC::Connection::dispatchIncomingMessages() + 576 19 JavaScriptCore 0x1ae386b8c WTF::RunLoop::performWork() + 524 20 JavaScriptCore 0x1ae386960 WTF::RunLoop::performWork(void*) + 36 21 CoreFoundation 0x196badce4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 22 CoreFoundation 0x196badc78 __CFRunLoopDoSource0 + 172 23 CoreFoundation 0x196bac9fc __CFRunLoopDoSources0 + 232 24 CoreFoundation 0x196babc3c __CFRunLoopRun + 840 25 CoreFoundation 0x196bd0700 CFRunLoopRunSpecific + 572 26 GraphicsServices 0x1e3711190 GSEventRunModal + 168 27 UIKitCore 0x1997ee240 -[UIApplication _run] + 816 28 UIKitCore 0x1997ec470 UIApplicationMain + 336 29 Telstra PTT 0x1004d30c8 main + 56 30 dyld 0x1bd5d3ad8 start + 5964
4
1
382
Oct ’25
Does BGAppRefreshTask require an internet connection?
Basically the title. I am trying to implement a local notification to trigger, regardless of internet connection, around 3-5pm if a certain array in the app is not empty to get the user to sync unsaved work with the cloud. I wanted to used the BGAppRefreshTask as I saw it was lightweight and quick for just posting a banner notification but after inspecting it in the console, it looks like it needs internet connection to trigger. Is this the case or am I doing something wrong? Should I be using the BGProcessingTask instead?
1
0
116
Jul ’25
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!
Replies
2
Boosts
0
Views
248
Activity
Dec ’25
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.
Replies
7
Boosts
0
Views
403
Activity
Jan ’26
Can an app launch automatically after watchOS restarts?
Regarding App Update Synchronization During Workout Mode: My watchOS app has workout mode enabled. When I update the app from the App Store on my iPhone while a workout session is active on my Apple Watch, the update does not sync to the watch. Why does this happen, and when can I expect the watch app to be updated? Regarding Automatic App Launch After a Prolonged Shutdown: I would like my watchOS app to launch automatically on my Apple Watch after it has been powered off for an extended period and then turned back on. Is this functionality possible to implement? If not, please provide a definitive answer regarding this capability.
Replies
1
Boosts
0
Views
191
Activity
Jan ’26
nonisolated Execution Differences Before and After Xcode 26.2
I have an older project that was created before Xcode 26.2. In Xcode versions prior to 26.2, there was no Swift Compiler – Concurrency build setting. With those older versions, the following behavior occurs: a nonisolated function executes off the main thread. class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() run() } private func run() { Task { await runInMainThread() } } func runInMainThread() async { print(">>>> IN runInMainThread(), Thread.isMainThread \(Thread.isMainThread)") await runInBackgroundThread() } private nonisolated func runInBackgroundThread() async { print(">>>> IN runInBackgroundThread(), Thread.isMainThread \(Thread.isMainThread)") } } Output: >>>> IN runInMainThread(), Thread.isMainThread true >>>> IN runInBackgroundThread(), Thread.isMainThread false However, starting with Xcode 26.2, Apple introduced the Swift Compiler – Concurrency settings. When running the same code with the default configuration: Approachable Concurrency = Yes Default Actor Isolation = MainActor This is the output Output: >>>> IN runInMainThread(), Thread.isMainThread true >>>> IN runInBackgroundThread(), Thread.isMainThread true the nonisolated function now executes on the main thread. This raises the following questions: What is the correct Swift Compiler – Concurrency configuration if I want a nonisolated function to run off the main thread? Is nonisolated still an appropriate way to ensure code runs on a background thread?
Replies
3
Boosts
0
Views
251
Activity
Feb ’26
Capturing screen buffer at macOS Login Window with ScreenCaptureKit and PrivilegedHelper
I am developing a remote support tool for macOS. While we have successfully implemented a Privileged Helper Tool and LaunchDaemon architecture that works within an active Aqua session, we have observed a total failure to capture the screen buffer or receive input at the macOS Login Window. Our observation of competitor software (AnyDesk, TeamViewer) shows they maintain graphical continuity through logout/restart. We are seeking the official architectural path to replicate this system-level access. Current Technical Implementation Architecture: A root-level LaunchDaemon manages the persistent network connection. A PrivilegedHelperTool (installed in /Library/PrivilegedHelperTools/) is used for elevated tasks. Environment: Tested on macOS 14.x (Sonoma) and macOS 15.x (Sequoia) on Apple Silicon. Capture Methods: We have implemented ScreenCaptureKit (SCK) as the primary engine and CGDisplayCreateImage as a fallback. Binary Status: All components are signed with a Developer ID and have been successfully Notarized. Observed Behavior & Blockers The "Aqua" Success: Within a logged-in user session, our CGI correctly identifies Display IDs and initializes the capture stream. Remote control is fully functional. The "Pre-Login" Failure: When the Mac is at the Login Window (no user logged in), the following occurs: The Daemon remains active, but the screen capture buffer returns NULL or an empty frame. ScreenCaptureKit fails to initialize, citing a lack of graphical context. No TCC (Transparency, Consent, and Control) prompt can appear because no user session exists. The "Bootstrap" Observation: We have identified that the loginwindow process exists in a restricted Mach bootstrap namespace that our Daemon (running in the System domain) cannot natively bridge. Comparative Analysis (Competitor Benchmarking) We have analyzed established remote desktop solutions like AnyDesk and Jump Desktop to understand their success at the login screen. Our findings suggest: Dual-Context Execution: They appear to use a Global LaunchAgent with LimitLoadToSessionType = ["LoginWindow"]. This allows a child process to run as root inside the login window’s graphical domain. Specialized Entitlements: These apps have migrated to the com.apple.developer.persistent-content-capture entitlement. This restricted capability allows them to bypass the weekly/monthly TCC re-authorization prompts and function in unattended scenarios where a user cannot click "Allow." Questions Entitlement Requirement: Is the persistent-content-capture entitlement the only supported way for a third-party app to capture the LoginWindow buffer without manual user intervention? LaunchAgent Strategy: To gain a graphical context at the login screen, is it recommended to load a specialized agent into the loginwindow domain via launchctl bootstrap loginwindow ...? ScreenCaptureKit vs. Legacy: Does ScreenCaptureKit officially support the LoginWindow session, or does it require an active Aqua session to initialize? MDM Bypass: For Enterprise environments, can a Privacy Preferences Policy Control (PPPC) payload grant "Screen Recording" to a non-entitled Daemon specifically for the login window context?
Replies
1
Boosts
0
Views
482
Activity
Jan ’26
Where did I screw up trying concurrency?
I tried making a concurrency-safe data queue. It was going well, until memory check tests crashed. It's part of an unadvertised git project. Its location is: https://github.com/CTMacUser/SynchronizedQueue/commit/84a476e8f719506cbd4cc6ef513313e4e489cae3 It's the blocked-off method "`memorySafetyReferenceTypes'" in "SynchronizedQueueTests.swift." Note that the file and its tests were originally AI slop.
Replies
2
Boosts
0
Views
295
Activity
Feb ’26
Apps closed in background without crashlog or hint
Knows anyone a point in systemlog etc. To find out when and why my or other apps are terminated by os. At the moment a lot of apps inclusive my apps seems to be terminated instead set to sleep by OS if no power coord is connected There are no crashlogs recorded, Sentry or firebase don‘t report issues.
Replies
3
Boosts
0
Views
179
Activity
Feb ’26
Inter-app Communication with Third Party SDK
I’ve built an app that connects via Bluetooth to a device. The device sends up, down, left and right commands. I want to build an SDK for other third party developers to use so that whenever a third party app with the SDK opens, if we press a button on the device, my app which captures the button press should be able to forward the event to the third party app. I want to achieve this with the lowest latency possible so that I can enable a variety of use cases like simple games and interactions within other apps. What would be the best way for me to achieve this as part of my SDK and my app?
Replies
3
Boosts
0
Views
279
Activity
Feb ’26
Trouble creating an XPC service for out-of-process rendering
I'm working on an editor for Bevy games and wanted the following workflow: Launch the game process Host a Metal view for the game's render target Use an XPC service to transfer an MTLSharedTextureHandle Keep the connection for editor/game communication and hot reload As such I created the following editor service: public let XPCEditorServiceName = "org.bevy.editor" public enum XPCEditorMessage: Codable { case ping } public enum XPCEditorReply: Codable { case pong } extension XPCListener { static let bevy = try! XPCListener(service: XPCEditorServiceName) { request in request.accept(XPCEditorService.init) } } struct XPCEditorService: XPCPeerHandler { let session: XPCSession private func handle(_ message: XPCEditorMessage) -> XPCEditorReply? { switch message { case .ping: return .pong } } func handleIncomingRequest(_ message: XPCReceivedMessage) -> (any Encodable)? { do { return handle(try message.decode()) } catch { return nil } } func handleCancellation(error: XPCRichError) { print(error) } } and I initialize it in my app's App initializer: // Launch the XPC service print(XPCListener.bevy) I wanted to test this using an executable target with the following main.swift: let session = try XPCSession(xpcService: XPCEditorServiceName) let response: XPCEditorReply = try session.sendSync(XPCEditorMessage.ping) print("Connected to editor!") The editor prints Listener<org.bevy.editor>(Active) but the game fails with Underlying connection was invalidated. Reason: Connection init failed at lookup with error 3 - No such process What am I doing wrong? PS. Would also appreciate an example of sending & rendering the MTLSharedTextureHandle both in editor & game.
Replies
2
Boosts
0
Views
142
Activity
Feb ’26
Migrating away from SMJobBless
I have migrated my code to use SMAppService but am running into trouble deleting the old SMJobBless launchd registration using launchd remove. I am invoking this from a root shell when I detect the daemon and associated plist still exist, then also deleting those files. The remove seems to work (i.e. no errors returned) but launchd list shows the service is registered, with a status code of 28 I am using the same label for SMAppService as previously and suspect this is the reason for the problem. However, I am reluctant to change the label as there will a lot of code changes to do this. If I quit my application, disable the background job in System Settings and run sudo launchd remove in the Terminal then it is removed and my application runs as expected once the background job is re-enabled. Alternatively, a reboot seems to get things going. Any suggestions on to how I could do this more effectively welcome.
Replies
2
Boosts
0
Views
150
Activity
Mar ’26
Unix Domain Socket path for IPC between LaunchDaemon and LaunchAgent
Hello, I am working on a cross-platform application where IPC between a LaunchDaemon and a LaunchAgent is implemented via Unix domain sockets. On macOS, the socket path length is restricted to 104 characters. What is the Apple-recommended directory for these sockets to ensure the path remains under the limit while allowing a non-sandboxed agent to communicate with a root daemon? Standard paths like $TMPDIR are often too long for this purpose. Thank you in advance!
Replies
4
Boosts
0
Views
221
Activity
Mar ’26
Clarification on concurrency guarantees for shared data between App and Widget extensions
Hi, I’m looking for clarification on what concurrency and consistency guarantees Apple provides when multiple targets (main app + Widget extensions) access shared storage. Specifically: 1. UserDefaults (App Group / suiteName:) • If multiple processes (app + multiple widget instances) read and write the same shared UserDefaults, what guarantees are provided? • Is access serialized internally to prevent corruption? • Are read–modify–write operations safe across processes, or can lost updates occur? 2. Core Data (shared SQLite store in App Group container) • Is it officially supported for multiple processes to open and write to the same Core Data SQLite store? • Are there recommended configurations (e.g. WAL mode) for safe multi-process access? • Is Apple’s recommendation to have a single writer process? 3. FileManager (shared container files) • If two processes write to the same file in an App Group container, what guarantees are provided by the system? • Is atomic replaceItemAt the recommended pattern for safe cross-process updates? Additionally: • Do multiple widget instances count as separate processes with respect to these guarantees? • Is there official guidance on best practices for shared persistence between app and widget extensions? I want to ensure I’m following the correct architecture and not relying on undefined behavior. Thanks.
Replies
1
Boosts
0
Views
175
Activity
Mar ’26
How to launch a sandboxed process as a standalone application?
Hello, I have an application that needs to be published to the App Store. This application consists of two processes, A and B, where B is a child process of A. I found that if process B needs to be launched as a child process of A in sandbox mode, it is necessary to set the following keys in the entitlements.plist file: <key>com.apple.security.app-sandbox</key><true/><key>com.apple.security.inherit</key><true/> However, after setting these keys, process B can no longer be launched directly. This issue is particularly prominent because process B has a window and a Dock icon — in this case, if the user pins the Dock icon, they will be unable to launch process B. Could you please advise on a solution to this problem?
Replies
1
Boosts
0
Views
155
Activity
Mar ’26
BGProcessingTask expirationHandler — No way to distinguish expiration reason
The expirationHandler on BGProcessingTask is a () -> Void closure. It provides no information about why it was called. In my testing, all of the following trigger the same handler: Time expiration Resource pressure (CPU, memory, battery) Not reporting progress User tapping "Stop" on the Live Activity There is no way for the app to tell these apart. Questions: Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires." Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions? Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently this is impossible. Environment: iOS 26, physical device
Replies
1
Boosts
0
Views
105
Activity
Mar ’26
BGProcessingTask expirationHandler — No way to distinguish expiration reason
The expirationHandler on BGProcessingTask is a () -> Void closure. It provides no information about why it was called. In my testing, all of the following trigger the same handler: Time expiration Resource pressure (CPU, memory, battery) Not reporting progress User tapping "Stop" on the Live Activity There is no way for the app to tell these apart. Questions: Q1. Is there an official, complete list of all conditions that trigger expirationHandler? The documentation only mentions "time expires." Q2. What is the specific time limit before timeout? If it varies by device state, what are the conditions? Q3. A way to distinguish the reason is needed. "User stop" and "system expiration" require completely different handling. Currently this is impossible. Environment: iOS 26, physical device
Replies
5
Boosts
0
Views
199
Activity
4w
Securing XPC Daemon Communication from Authorization Plugin
I'm working on securing communication between an Authorization Plugin and an XPC daemon, and I’d appreciate some guidance on best practices and troubleshooting. The current design which, I’ve implemented a custom Authorization Plugin for step-up authentication, which is loaded by Authorization Services at the loginwindow (inside SecurityAgent). This plugin acts as an XPC client and connects to a custom XPC daemon. Setup Details 1. XPC Daemon Runs as root (LaunchDaemon) Not sandboxed (my understanding is that root daemons typically don’t run sandboxed—please correct me if this is wrong) Mach service: com.roboInc.AuthXpcDaemon Bundle identifier: com.roboInc.OfflineAuthXpcDaemon 2. Authorization Plugin Bundle identifier: com.roboInc.AuthPlugin Loaded by SecurityAgent during login 3. Code Signing Both plugin and daemon are signed using a development certificate What I’m Trying to Achieve I want to secure the XPC communication so that: The daemon only accepts connections from trusted clients The plugin only connects to the legitimate daemon Communication is protected against unauthorized access The Issue I'm facing I attempted to validate code signatures using: SecRequirementCreateWithString SecCodeCopyGuestWithAttributes SecCodeCheckValidity However, validation consistently fails with: -67050 (errSecCSReqFailed) Could you please help here What is the recommended way to securely authenticate an Authorization Plugin (running inside SecurityAgent) to a privileged XPC daemon? Since the plugin runs inside SecurityAgent, how can the daemon reliably distinguish my plugin from other plugins? What is the correct approach to building a SecRequirement in this scenario? Any guidance, examples, or pointers would be greatly appreciated. Thanks in advance!
Replies
6
Boosts
0
Views
281
Activity
2w
FIFinderSync Extension fails to load on FIFinderSync Extension fails to load on macOS 26.3.1 (a) (25D771280a)
(! status in pluginkit, FinderSyncExtensionHost process missing) macOS Version: 26.3.1 Beta (25D771280a) Xcode Version: 16.3 (17C529) Steps to reproduce: Create a Finder Sync Extension project Build and install to /Applications Enable in System Settings → Extensions → Finder Extensions Extension shows ! in pluginkit output FinderSyncExtensionHost process never starts Context menu never appears in Finder Expected: Extension loads and context menu appears Actual: Extension marked with ! in pluginkit, no process launched pluginkit output: ! com.github.astronautJack.EasyNewFile.EasyNewFileExtension(1.0)
Replies
1
Boosts
0
Views
94
Activity
3w
How to debug a Launch Daemon that requires an App Group provisioning profile for XPC communication
Hello, I am developing a macOS Launch Daemon (packaged as a bundle) that acts as an XPC server. For debugging purposes, I am trying to run the daemon's executable directly from the terminal via sudo ./mydaemon.app/Contents/MacOS/myexecutable. Initially, I added the com.apple.security.application-groups entitlement to the daemon. However, when starting the process, it failed to create the XPC service with the following errors: Unsatisfied entitlements: com.apple.security.application-groups Soft-restriction provisioning profile validation failure: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=, unsatisfiedEntitlements=, NSLocalizedDescription=No matching profile found} listener failed to activate: xpc_error=[1: Operation not permitted] To resolve the profile validation failure, I registered a new App Group in the Apple Developer Portal, generated a new provisioning profile for the daemon that includes this group, and embedded it into the bundle (Contents/embedded.provisionprofile). Now, the previous profile error is gone, but I am getting a new identity conflict error, and the XPC listener still fails: Two equal instances have unequal identities. <anon<myproc_name>(501) pid=2818 AUID=501> and <anon<myproc_name>(501)(262) pid=2818 AUID=262> listener failed to activate: xpc_error=[1: Operation not permitted] My questions are: What exactly causes the Two equal instances have unequal identities error? I noticed the Audit UID difference (AUID=501 vs AUID=262). Why does NSXPCListener still fail with Operation not permitted? What is the recommended workflow for debugging a Launch Daemon that requires an App Group provisioning profile for XPC communication? Thank you in advance!
Replies
2
Boosts
0
Views
99
Activity
1w
App Terminated with 0x8BADF00D: Main Thread Blocked During Back-to-Back Messaging
Hello, I'm experiencing an issue with my app where it's being terminated by the system with a watchdog violation during back-to-back messaging operations. I've analyzed the crash logs but would appreciate additional insights on optimizing my approach. I'd appreciate any insights on how to resolve this problem. Crash Details: Exception Type: EXC_CRASH (SIGKILL) Termination Reason: FRONTBOARD with code 0x8BADF00D Error: "scene-update watchdog transgression: app exhausted real time allowance of 10.00 seconds" Reproduction Steps: User A initiates back-to-back messages to other User User A's UI becomes unresponsive and eventually the app crashes. Stack Trace Analysis: The crash occurs on the main thread, which appears to be blocked waiting for a condition in the keyboard handling system. The thread is stuck in [UIKeyboardTaskQueue _lockWhenReadyForMainThread] and related methods, suggesting an issue with keyboard-related operations during the messaging process. Crash Tag Exception Type: EXC_CRASH (SIGKILL) Exception Codes: 0x0000000000000000, 0x0000000000000000 Termination Reason: FRONTBOARD 2343432205 <RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: app<com.msikodiak.eptt(AD934F8A-DF57-4B75-BE73-8CF1A9A8F856)>:301 exhausted real (wall clock) time allowance of 10.00 seconds ProcessVisibility: Foreground ProcessState: Running WatchdogEvent: scene-update WatchdogVisibility: Background WatchdogCPUStatistics: ( "Elapsed total CPU time (seconds): 6.390 (user 3.640, system 2.750), 11% CPU", "Elapsed application CPU time (seconds): 0.020, 0% CPU" ) ThermalInfo: ( "Thermal Level: 0", "Thermal State: nominal" ) reportType:CrashLog maxTerminationResistance:Interactive> Triggered by Thread: 0 Thread 0 name: Dispatch queue: com.apple.main-thread Thread 0 Crashed: 0 libsystem_kernel.dylib 0x1e773d438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x2210bc328 _pthread_cond_wait + 1028 2 Foundation 0x1957d8a64 -[NSCondition waitUntilDate:] + 132 3 Foundation 0x1957d8888 -[NSConditionLock lockWhenCondition:beforeDate:] + 80 4 UIKitCore 0x1998f1238 -[UIKeyboardTaskQueue _lockWhenReadyForMainThread] + 456 5 UIKitCore 0x19a3d775c __59-[UIKeyboardImpl updateAutocorrectPrompt:executionContext:]_block_invoke_9 + 28 6 UIKitCore 0x19986b084 -[UIKeyboardTaskQueue lockWhenReadyForMainThread] + 168 7 UIKitCore 0x19a3f2994 -[UIKeyboardTaskQueue waitUntilTaskIsFinished:] + 148 8 UIKitCore 0x19a3f2ac4 -[UIKeyboardTaskQueue performSingleTask:breadcrumb:] + 132 9 UIKitCore 0x199e2f7e4 -[_UIKeyboardStateManager updateForChangedSelection] + 144 10 UIKitCore 0x199e24200 -[_UIKeyboardStateManager invalidateTextEntryContextForTextInput:] + 92 11 WebKit 0x1ad52fa54 WebKit::PageClientImpl::didProgrammaticallyClearFocusedElement(WebCore::ElementContext&&) + 40 12 WebKit 0x1ad55adcc WebKit::WebPageProxy::didProgrammaticallyClearFocusedElement(WebCore::ElementContext&&) + 136 13 WebKit 0x1acec74e8 WebKit::WebPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 18604 14 WebKit 0x1acd21184 IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 236 15 WebKit 0x1ace449b8 WebKit::WebProcessProxy::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 40 16 WebKit 0x1ace44228 WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 1764 17 WebKit 0x1acd1e904 IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 268 18 WebKit 0x1acd1e478 IPC::Connection::dispatchIncomingMessages() + 576 19 JavaScriptCore 0x1ae386b8c WTF::RunLoop::performWork() + 524 20 JavaScriptCore 0x1ae386960 WTF::RunLoop::performWork(void*) + 36 21 CoreFoundation 0x196badce4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28 22 CoreFoundation 0x196badc78 __CFRunLoopDoSource0 + 172 23 CoreFoundation 0x196bac9fc __CFRunLoopDoSources0 + 232 24 CoreFoundation 0x196babc3c __CFRunLoopRun + 840 25 CoreFoundation 0x196bd0700 CFRunLoopRunSpecific + 572 26 GraphicsServices 0x1e3711190 GSEventRunModal + 168 27 UIKitCore 0x1997ee240 -[UIApplication _run] + 816 28 UIKitCore 0x1997ec470 UIApplicationMain + 336 29 Telstra PTT 0x1004d30c8 main + 56 30 dyld 0x1bd5d3ad8 start + 5964
Replies
4
Boosts
1
Views
382
Activity
Oct ’25
Does BGAppRefreshTask require an internet connection?
Basically the title. I am trying to implement a local notification to trigger, regardless of internet connection, around 3-5pm if a certain array in the app is not empty to get the user to sync unsaved work with the cloud. I wanted to used the BGAppRefreshTask as I saw it was lightweight and quick for just posting a banner notification but after inspecting it in the console, it looks like it needs internet connection to trigger. Is this the case or am I doing something wrong? Should I be using the BGProcessingTask instead?
Replies
1
Boosts
0
Views
116
Activity
Jul ’25