Hi Kevin,
Q - How we know didFinishLaunchingWithOptions is not being called at user-visible launch time
We agree that the most important question here is when the app was actually initialized versus when the user opens it.
To address this, we have implemented explicit lifecycle logging at the very earliest entry points of the app, including:
A log at process start
Logs at the very beginning and end of application(_:didFinishLaunchingWithOptions:)
Logs for all other UIApplication lifecycle callbacks
We log all lifecycle events (including process start and didFinishLaunchingWithOptions) using a dedicated serial queue and persist them directly to disk.
In simplified terms, our logging flow is:
Logs are written via a serial logQueue
Each log entry is appended to a file in the app’s Documents directory
Logs include:
ISO timestamps
Explicit lifecycle markers
The process ID (pid)
This means:
Logs are persisted to disk, not memory
Logs survive suspension and backgrounding
We do not clear or rotate logs on background transitions
Each app process appends to the same log file
How far back the logs go
Logs accumulate over time and remain available until explicitly uploaded
We upload the full log file to our backend (AWS) at specific trigger points
Because logs are file-based, they capture events that occurred many hours earlier
This allows us to determine:
Whether a new process was created
Whether didFinishLaunchingWithOptions was entered for that process
Whether a user-visible launch is happening within an already-running (or resurrected) process
In the problematic cases:
The pid remains the same
There is no PROCESS_STARTED
There is no DID_FINISH_LAUNCHING_START
The app resumes directly into applicationDidBecomeActive(_:)
This behavior is consistently reproducible on supervised MDM devices and has not been observed on non-MDM devices so far.
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags: