DeviceActivityReportExtension sandbox blocks all output channels — how to export resolved Application.bundleIdentifier?
Application.bundleIdentifier only resolves to a non-nil value inside a DeviceActivityReportExtension (ExtensionKit/XPC). The main app and DeviceActivityMonitor extension always return nil.
However, the Report Extension's sandbox silently blocks every output channel I've tested:
UserDefaults (App Group): Reads succeed, writes silently dropped
File writes (App Group container): Fail silently or throw
HTTP requests: Network blocked entirely
Local Notifications: "Couldn't communicate with a helper application"
UIPasteboard: Writes silently fail
iCloud KVS: synchronize() returns false
Both targets share the same com.apple.security.application-groups entitlement and group identifier. The main app reads and writes to the shared container normally — only the extension's writes fail.
This means resolved bundle identifiers can only be rendered in the extension's own SwiftUI view and cannot be communicated anywhere else.
My question:
Is this sandbox restriction intentional? If so, what is the recommended mechanism for the host app (or a backend) to obtain the resolved bundle identifiers that only the Report Extension can access?
Environment: Xcode 16.3, iOS 18.3, physical device.
Sample project: https://drive.google.com/file/d/1DPyN2BCUt5p-RKEPA0zsDFFEvgZVHlS_/view?usp=sharing — a minimal two-target project that demonstrates every failing channel. Run on a physical device, grant Screen Time access, select apps,
and observe that bundle ID resolution shows PASS but all write channels show FAIL.
General
RSS for tagDelve into the world of built-in app and system services available to developers. Discuss leveraging these services to enhance your app's functionality and user experience.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
Hello,
I am wondering if an app that does the following is possible or is impossible due to ios limitations for apps?
An app that access all sms messages, and or all phone calls logs? (goal is to save them and not have to filter them manually)
An app that control OTHER apps permissions and or read permissions status of all other apps?
Topic:
App & System Services
SubTopic:
General
I am working on an e-commerce app (retail/marketplace) that allows users to place orders for both free and paid products. After receiving a DeclaredAgeRange API response — retrieved via the Family Controls / Screen Time framework — indicating that a user is a minor, I want to understand the recommended approach for handling payment flows.
Specifically, is it necessary to block payments for users identified as minors via DeclaredAgeRange, even though our app uses server-side encrypted card processing rather than Apple In-App Purchases (StoreKit)?
Any guidance on best practices or App Store policy requirements for this scenario would be greatly appreciated.
I am working on an e-commerce app (retail/marketplace) that allows users to place orders for both free and paid products. After receiving a DeclaredAgeRange API response — retrieved via the Family Controls / Screen Time framework — indicating that a user is a minor, I want to understand the recommended approach for handling payment flows.
Specifically, is it necessary to block payments for users identified as minors via DeclaredAgeRange, even though our app uses server-side encrypted card processing rather than Apple In-App Purchases (StoreKit)?
Any guidance on best practices or App Store policy requirements for this scenario would be greatly appreciated.
I am building a simple iOS app that shows the total phone usage time for today using the Screen Time APIs.
Architecture:
Main app
→ requests authorization using AuthorizationCenter.shared.requestAuthorization(for: .individual)
→ displays a DeviceActivityReport
Report extension
→ DeviceActivityReportExtension
→ calculates total usage using DeviceActivityResults<DeviceActivityData>
→ shows the number in a SwiftUI view
The report works correctly. The extension successfully calculates the total usage and displays it on screen.
Example logic inside the report extension:
for await activityData in data {
for await segment in activityData.activitySegments {
totalSeconds += segment.totalActivityDuration
}
}
let totalMinutes = Int(totalSeconds / 60)
The problem:
I need the main app to access that number so I can store it daily in my own database.
I tried to send the value from the extension to the main app using:
App Group + UserDefaults(suiteName:)
App Group + shared file (FileManager.containerURL)
writing inside makeConfiguration(...)
Example:
if let defaults = UserDefaults(suiteName: "group.myapp") {
defaults.set(value, forKey: "savedTotalActivity")
}
But the main app cannot read the value. The report extension displays the number correctly, but the data never appears in shared storage.
Questions:
Is DeviceActivityReportExtension intentionally sandboxed so Screen Time data cannot be exported to the containing app?
Is there any supported way for the main app to access the total usage value calculated in the report extension?
If exporting the value is restricted, what is the recommended architecture for apps that want to store daily Screen Time totals for later analysis?
Goal:
I want a simple app that records something like:
2026-03-08 → 244 minutes
2026-03-09 → 198 minutes
and stores it inside the app database.
Any guidance on the correct architecture would help.
I've run into what appears to be a bug in PDFKit's radio button serialization.
When creating a radio button group with PDFAnnotation, only the first annotation added via page.addAnnotation() gets a correct /AS entry in the written PDF — all other annotations always get /AS /Off, regardless of buttonWidgetState.
Minimal reproduction
func makeRadioButton(optionId: String, isSelected: Bool) -> PDFAnnotation {
let ann = PDFAnnotation(bounds: CGRect(x: 0, y: 0, width: 20, height: 20),
forType: .widget, withProperties: nil)
ann.widgetFieldType = .button
ann.widgetControlType = .radioButtonControl
ann.fieldName = "Choice"
ann.buttonWidgetStateString = optionId
ann.buttonWidgetState = isSelected ? .onState : .offState
return ann
}
let pdf = PDFDocument()
let page = PDFPage()
pdf.insert(page, at: 0)
// Intend to select B
page.addAnnotation(makeRadioButton(optionId: "A", isSelected: false))
page.addAnnotation(makeRadioButton(optionId: "B", isSelected: true))
page.addAnnotation(makeRadioButton(optionId: "C", isSelected: false))
_ = pdf.dataRepresentation()
// Result: /AS is /Off for all three — B is not selected in the PDF
What I observed
Selecting A (first annotation added): /AS /A written correctly works
Selecting B or C: /AS /Off for all buttons
Additionally, dataRepresentation() corrupts the in-memory state as a side effect: buttonWidgetState of the selected annotation is .onState before the call and .offState after.
Root cause
During serialization, dataRepresentation() internally calls setButtonWidgetState:.onState on each annotation in turn to generate appearance streams. This triggers PDFKit's radio-group exclusivity logic, which silently clears all other annotations — so by the time /AS is written, only the first annotation's selection survives.
Workaround
It took a while to track this down, so I'm documenting the workaround here in case it helps others.
Add the annotation that should be selected first via page.addAnnotation():
// Add selected annotation first
page.addAnnotation(makeRadioButton(optionId: "B", isSelected: true))
page.addAnnotation(makeRadioButton(optionId: "A", isSelected: false))
page.addAnnotation(makeRadioButton(optionId: "C", isSelected: false))
Tested on macOS 26.3 / Xcode 26.3. Filed as Feedback FB22167174.
Full code including workaround is here:
radio_bug_swift.txt
Has anyone else hit this? Is there a cleaner method I'm missing?
Our watchOS app is exploring adding audio VOIP calling capability using our in-home platform. We are using LiveCommunicationKit for this and have that all hooked up nicely in a proof of concept implementation.
Our use case is primarily based around supporting end-users through various tasks with assistance from a remotely based expert. We would like for our platform to be able to display visual content on the watch's screen during the call – in other words, we would like to be able to treat this as a video call.
LiveCommunicationKit fully supports all video-related flags on watchOS and doesn't appear to have any different symbol availability versus its iOS version. This high-quality thread (https://developer.apple.com/forums/thread/798090) from a DTS engineer suggests that our use case should be valid (i.e. whiteboarding apps) and that the system's response to an accepted income video call is to dismiss the LCK's incoming call screen and bring the target app to the foreground, allowing it to render its custom content. Unfortunately, on watchOS the system doesn't seem to treat a video call any differently from an audio call, and won't dismiss the system UI once it's answered.
We fully realize that Apple Watch doesn't have a camera for outbound video, doesn't support VideoToolbox or other low-level video convenience libraries for simplified rendering and decoding, etc. That's not what we're worried about (yet). The documentation is at best unclear about whether LCK (or CallKit, for that matter) can hand off calls flagged as video-compatible according to how we think they should, which is passing foreground UI over to the app once the call has been accepted by the user.
Can any Apple people shed some light on this? I recognize we are probably trying to do something not many people have before.
Hello,
I’m implementing VoIP calling in an iOS application using PushKit (VoIP pushes) together with CallKit.
The standard call flow works correctly:
Happy scenario
User A initiates a call.
Server sends a VoIP push to User B.
User B’s device receives the push and reports the incoming call using CallKit.
User B answers the call.
However, I would like clarification about non-happy scenarios and when it is acceptable to use VoIP pushes to update or stop a CallKit ringing state.
Apple documentation warns that VoIP pushes must be used only when they result in a call-related action, so I want to ensure the following cases are compliant.
Scenario A — Caller Cancels Before Answer
User A calls User B.
Server sends a VoIP push to User B.
User B’s device starts ringing via CallKit.
Before User B answers, User A cancels the call.
Question:
Is it acceptable to send another VoIP push to User B indicating that the call has been cancelled so the device can:
stop the CallKit ringing UI
end the call
optionally mark it as missed or cancelled
Or should this state change be handled using a regular remote push or another signaling mechanism instead of VoIP push?
Scenario B — Callee Rejects the Call
User B rejects the call from CallKit.
The server must inform User A that the call was rejected.
Question:
Is it acceptable to send a VoIP push to User A to update the CallKit state and terminate the outgoing call UI?
Scenario C — Multiple Devices per User
User B may be logged in on multiple devices.
User A calls User B.
VoIP push is sent to all devices of User B.
One device answers.
Question:
Is it acceptable to send a VoIP push to the remaining devices instructing them to:
stop ringing
end the CallKit incoming call UI
Or is there a recommended alternative pattern for this case?
Main Question
Aside from the initial incoming call VoIP push, in which situations is it considered acceptable to send additional VoIP pushes to terminate or update CallKit state (cancelled, rejected, answered on another device)?
The goal is to remain compliant with PushKit policies, particularly the guidance that VoIP pushes should only be used when they result in a call-related user action.
Any guidance on the recommended architecture for these cases would be greatly appreciated.
Thank you.
We’ve been implementing LiveCallerId using OHTTP and have hit a wall with the production environment. The setup works perfectly in TestFlight, but the release version of the app is consistently being rejected by the Apple OHTTP Relay when trying to tunnel traffic to our gateway.
Timeline & Status:
Applied via the form in September 2025.
Received confirmation in November 2025 that our /.well-known/ohttp-keys endpoint was correctly configured.
Since then, we've struggled to get a dialogue with Apple to confirm the final production whitelisting.
Technical Observations:
Our ohttp-keys endpoint is being polled frequently (every few minutes). Based on the traffic, this is clearly the Apple Relay infrastructure fetching/refreshing the keys, not the devices themselves. This suggests the Relay "sees" our configuration, yet it still refuses to tunnel traffic to our gateway in the production environment.
Since everything is functional in TestFlight, our implementation seems correct. It feels like there is a configuration mismatch or a missing "production flip" on the Relay side for our Bundle ID.
If anyone from the Apple engineering team could verify the status for this Bundle ID, it would be a huge help. We've been stuck in this "TestFlight-only" state for quite a while now.
Hey everyone,
I'm developing an iOS only app and want to make sure it can not be installed on iPads.
Using Xcode 26, Targets/Appname/General/Supported Destination - I have iPhone only as destination and in the Info.plist I have this:
UIDeviceFamily
1
UIRequiredDeviceCapabilities
telephony
Is there anything else need to do to make sure it can't be installed on iPads? Thanks in advance
We are operating an application that uses WeatherKit.
Despite revoking a specific WeatherKit key on the Apple Developer website,
the number of API calls associated with that key continues to increase.
We are looking for a way to completely disable this particular key.
Any advice or suggestions would be greatly appreciated.
I have gotten all necessary entitlements for all my extensions, but screen time still does not work in Testflight.
our app blocks social apps for a particular period of time..
This feature works in my Xcode physical device but fails in testflight
I'm building an app that uses the Family Controls / Screen Time APIs (FamilyControls, ManagedSettings). My app has three targets, each with a distinct Bundle ID:
Main App
Shield Configuration Extension
ShieldAction Extension
All three have com.apple.developer.family-controls in their entitlements files, and they share an App Group.
My question is about the distribution entitlement request form at developer.apple.com/contact/request/family-controls-distribution: does the form need to be submitted once per Bundle ID, or is a single submission for the main app sufficient to then enable Family Controls (Distribution) for the extension Bundle IDs in the developer portal as well?
I've seen conflicting reports in other forum threads — some developers say one submission covers all targets, others say separate submissions are needed per Bundle ID. I've already submitted the main app, but now I am wondering whether I should submit one for each Shield extension. Thanks!
Topic:
App & System Services
SubTopic:
General
Tags:
Family Controls
Device Activity
Managed Settings
Screen Time
Hi!
We’ve had Live Caller ID Lookup in production for a while. We’re seeing backend RPS on our /queries endpoint much higher than our expected incoming call volume.
While testing with Console.app during an incoming call, it looks like iOS may still hit our service even when the caller number is already in the user’s Contacts - but I’m not 100% sure from logs alone.
Can you confirm:
Does iOS invoke Live Caller ID Lookup (i.e. call /queries) for every incoming call, including calls from saved Contacts?
If yes, is this simply expected framework behavior?
Thanks!
While the recent news says "Developers who are distributing apps in Brazil can use the updated Declared Age Range API to obtain a user’s age category.", the guidance in the API did not mention Brazil. Can we confirm that
Should all iOS developers follow that guidance for Brazil compliance?
Will IsEligibleForAgeFeatures return true for in scope users in Brazil? (We don't have any explicit confirmation on this, and we cannot test if this is the case today in sandbox)
We have an iOS/iPadOS (mixed use of UIKit/SwiftUI) app on the App Store since a couple of years.
Over the last month or so, we are receiving many user reports complaining about app freezing and behaving very bad generally. The common denominator for all of these users (~10) is that they are using iPad Pro M4, 13 inch, and they are on at least iPadOS 26.2 - some have updated to 26.2.1, 26.3 etc but the problems remain. Some of the users say that they were using our app normally, until the release of 26.2, or perhaps 26.2.1, from when the problems seem to have started.
Some report the problems that go away when they "use another WiFi", or when they hold the device in portrait mode (it seems that many complaints seem to suggest that the problem is in when holding the device in landscape). Other say the app works fine if they start it without network enabled, and after enabling network, continue in the app.
While we currently do not have an iPad Pro M4 13 inch to test with, we haven't been able to reproduce the problem on any other device.
We haven't heard of any similar problems from users of other devices.
While we have no idea what is causing these problems, my feeling is that there might be a possibility that there is some kind of problem with iPad Pro M4 and the recent iPadOS versions.
Just reaching out to see if anyone else have seen anything similar.
Hi,
I’m building an iOS self accountability app using FamilyControls and DeviceActivity. I can show the user’s real Screen Time correctly inside a DeviceActivityReport extension on a real device, but I want to use that same daily total inside the main app for today’s log and leaderboard.
What I’m stuck on is getting that value back into the app. I tried App Groups, shared UserDefaults, a shared file in the app group container, and CFPreferences, but the report still only works as a display and the main app never receives the total.
Is there any Apple supported way to use the daily Screen Time total from a DeviceActivityReport extension inside the containing app, or is this intentionally display only?
Thanks.
Hello,
I'm trying to figure out why an Int is being inferred over my explicit Double
I'm parsing a CSV that contains 2 tables. I don't own the data so I'm not able to change it.
The first row contains one cell that's used as a title for the document
The second row is empty
The third row contains one cell that's used as the header for the first table
There is a header row for the table
There's a dynamic number of rows for this table
The an empty spacer row
There is a row that's used as a title for the second table
There is a header row for the table
There's a dynamic number of rows for this table
Im able to separate and create two DataFrame's from the data without issue. And this is the initializer I'm using.
DataFrame(
csvData: csvData,
rows: rows,
types: types,
options: options
)
Column names and their CSV types looks like this
var types: [String: CSVType] {
[
// ...
"Column 38": .double,
// ...
]
}
The data in the CSV is
0
nil
nil
nil
2
And this is what the one of the columns in question looks like when printed
▿ 38 :
┏━━━━━━━━━━━┓
┃ Column 38 ┃
┃ <Int> ┃
┡━━━━━━━━━━━┩
│ 0 │
│ nil │
│ nil │
│ nil │
│ 2 │
└───────────┘
- name : "Column 38"
- count : 5
▿ contents : PackedOptionalsArray<Int>
▿ storage : <PackedOptionalsStorage<Int>: 0x600000206360>
The docs state
/// - types: A dictionary of column names and their CSV types.
/// The data frame infers the types for column names that aren't in the dictionary.
Since types contains the column name and it's still being inferred, my assumption is that the issue involves the renaming of the header row when it has empty cells occurs after the types are checked.
Edit:
After setting hasHeaderRow: false from true and adjusting my row offset, the types are now being assigned correctly.
I'd recommend opening a feedback enhancement where renaming columns occurs before type assignment.
From the Feb 24 news, I understand that for all Apple users in Brazil with iOS26.2 and newer, isEligibleForAgeFeatures will eventually return true. Brazil is a "nonregulated region", and developers will need to handle all three situations of ask first/always share/never share.
Please correct me if I'm wrong above. A few questions follow on the eligibility check:
What's the return value of IsEligibleForAgeFeatures for a Brazilian user who has NOT touched the age range feature at all, thus hasn't picked one of the three options?
How can we test these cases? From the updated sandbox doc, there's more information on declined/approved, will those the same behaviors as a future Brazilian user? The doc used to say Texas, now it doesn't say any region.
On which date will Apple START to return true for IsEligibleForAgeFeatures for Brazilian users? I cannot find the exact date anywhere.
Will ALL of Brazil return true overnight, or is there some ramp up that developers need to be aware of?
Thanks a lot for sharing the guidance, and thanks in advance for more guidance to come!
Hi,
We’re building an iOS app that uses the Screen Time APIs (FamilyControls and DeviceActivity) to display a user’s own usage metrics inside the app.
With the appropriate permissions granted, we are successfully reading and presenting metrics such as:
Total screen time
Device pickups
These metrics are already visible to the user inside our app.
We would now like to introduce a user-initiated “Share” feature. The idea is to:
Render selected Screen Time metrics into a shareable image card generated locally on device.
Present the standard iOS share sheet (UIActivityViewController).
Allow the user to share that image to Messages, social apps, etc., if they choose.
Important clarifications:
This is fully user-initiated.
The app does not automatically transmit Screen Time data.
The metrics are already displayed in-app with user permission.
The share asset would be generated locally.
No background export or server-side posting would occur unless explicitly triggered by the user via the share sheet.
We are seeking clarification on whether there are any policy or API restrictions around:
Rendering Screen Time-derived metrics into a user-facing share card
Allowing user-initiated export of those metrics via the standard iOS share flow
Are there any additional privacy requirements, entitlement constraints, or App Review considerations we should be aware of when implementing this?
Thanks in advance for any guidance.
Topic:
App & System Services
SubTopic:
General
Tags:
App Tracking Transparency
Developer Tools
Screen Time
Privacy