Team-scoped keys introduce the ability to restrict your token authentication keys to either development or production environments. Topic-specific keys in addition to environment isolation allow you to associate each key with a specific Bundle ID streamlining key management.
For detailed instructions on accessing these features, read our updated documentation on establishing a token-based connection to APNs.
Delve 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
Activity
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?
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.
In the WWDC 2019 session "Extended Runtime for WatchOS apps" the video talks about an entitlement being required to use the HR sensor judiciously in the background.
It provides a link to request the entitlement which no longer works: http://developer.apple.com/contect/request/health-monitoring
The session video is also quite hard to find these days.
Does anyone know why this is the case?
Is the API and entitlement still available?
Is there a supported way to run, even periodically, in the background on the Watch app (ignoring the background observer route which is known to be unreliable) and access existing HR sensor data
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
WatchKit
Health and Fitness
watchOS
Apple Watch
Hello team,
I am trying to find out a way to block urls in the chrome browser if it is found in local blocked list cache. I found URL Filter Network very much suitable for my requirement. But I see at multiple places that this solution is only for Enterprise level or MDM or supervised device. So can I run this for normal user ? as my targeting audience would be bank users. One more thing how can I test this in development environment if we need supervised devices and do we need special entitlement ?
When trying to run sample project in the simulator then getting below error
I want to track down which part of an app contacts a given domain listed in its App Privacy Report.
Following the instructions given here I am able to capture a packet trace, but traffic to the domain in question is encrypted using QUIC.
Is there a way to insert e.g. mitmproxy into the capture process in order to get hold of the SSLKEYLOGFILE so that I can decrypt the traffic?
We have a macOS system extension with NETransparentProxyProvider which is able to intercept traffic and handle it. We also wanted to setup few search domains from our network extension. However, unlike PacketTunnelProvider, NEDNSSettings are completely ignored with NETransparentProxyProvider.
So whats the best way to setup few DNS search domains when using NETransparentProxyProvider.
In Getting started with In-App Purchase using StoreKit views and the corresponding sample project, Store simultaneously enumerates Transaction.unfinished and Transaction.updates.
Since, "if your app has unfinished transactions, the updates listener receives them once, immediately after the app launches," it appears that Transaction.unfinished would also receive the same unfinished transactions causing handle(updatedTransaction:) to be called for twice for each transaction, causing consumables to be double-counted.
Is this a bug in the sample? Is there more information on concurrent execution of unfinished and updates?
I have an iOS and iPadOS app that also runs on macOS Catalyst. The user is able to view their subscription using the SubscriptionStoreView with two SubscriptionOptionGroups.
The documentation does not mention these are supported on macOS Catalyst and the app crashes when attempting to show the SubscriptionStoreView on macOS Catalyst.
If not supported, how can the user manage their subscription on macOS?
Hi,
I am currently implementing a recurring payment feature using the Apple Pay JS API.
Based on the official demo (https://applepaydemo.apple.com/apple-pay-js-api), it appears that the recurringPaymentRequest object only supports a maximum of two stages: trialBilling and regularBilling.
However, our service requires a multi-stage billing model with three or more different cycles/amounts as shown below:
Example Schedule:
Stage 1: 2,000 JPY (2026-03-01 to 2026-04-01)
Stage 2: 1,500 JPY (2026-04-01 to 2026-10-01)
Stage 3: 1,000 JPY (2026-10-01 to 2027-10-01)
Stage 4: 500 JPY (Thereafter)
Questions:
Is there any way to directly define and display three or more different billing cycles/amounts on the Apple Pay payment sheet?
If the API is strictly limited to two stages, what is the Apple-recommended way to provide transparency for such complex schedules while remaining compliant with the guidelines? For instance, is it acceptable to set the final amount in regularBilling and explain the preceding stages in the billingAgreement or paymentDescription fields?
I would appreciate any insights or official guidance on this.
Best regards,
Topic:
App & System Services
SubTopic:
Apple Pay
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?
Hello,
We are experiencing an issue related to push notifications after updating devices to iOS 26.4 Beta.
Our system stores push notification tokens on the server by associating the device token with the device’s IDFV in the app.
After updating a device to iOS 26.4 Beta, we observed that the device token from a previously uninstalled version of the app remains valid for more than a week. As a result, two push notifications are delivered to the same device.
The situation is as follows:
The user installs the app and a device token is generated.
The user uninstalls the app.
Later, the user installs the app again and a new device token is generated.
However, the previous device token does not become invalid, even after more than a week.
Because IDFV changes when the app is reinstalled, our server cannot determine that the device belongs to the same user. Therefore, we cannot overwrite the old token with the new one on the server side.
Could you please advise:
Is this behavior expected in iOS 26.4 Beta?
How long does it normally take for a device token to become invalid after an app is uninstalled?
What is the recommended approach to prevent duplicate push notifications in this situation?
Any guidance would be greatly appreciated.
Best regards
On iOS 26.2 (23C55), DeviceActivityMonitor.eventDidReachThreshold fires intermittently for a daily schedule (00:00–23:59) even when iOS Screen Time shows 0 minutes for the selected apps that day. This causes premature shielding via ManagedSettings.
Environment: iPhone 13 Pro Max, iOS 26.2 (23C55). Event selection: 2 apps. Threshold: 30 minutes. Multiple TestFlight users report the same behavior across various app selections and thresholds. Intermittent (~50% of days); sometimes multiple days in a row. Not observed in testing prior to iOS 26.2.
Evidence: sysdiagnose + Screen Time screenshots (with 0 screen time on selected apps) + unified logs show UsageTrackingAgent notifying the extension that “unproductive from activity daily reached its threshold,” followed immediately by ManagedSettings shield being applied (extension reacting to the callback).
Filed Feedback Assistant: FB21450954.
Questions: Are others seeing this on 26.2? Does it correlate with restarting monitoring at interval boundaries or includesPastActivity settings?
Topic:
App & System Services
SubTopic:
General
Tags:
Family Controls
Device Activity
Managed Settings
Screen Time
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.
I haven’t come across any official documentation regarding the limit on the number of Network Extensions macOS can run. However, I did see some discussions suggesting that Apple might restrict this to 5 extensions in macOS Tahoe.
Is there any official confirmation on this?
Nao consigo confirmar que tenho mais de 18 anos. Nenhum cartão de crédito aceita, aparece tente mais tarde e a imagem da CNH também não é enviada aparece erro.
Topic:
App & System Services
SubTopic:
Hardware
I am testing a consumable in-app purchase in the StoreKit sandbox and I am seeing behavior that does not seem correct on repeat purchase attempts.
Product details
Product ID: album.credit.v2
Type: Consumable
Test environment: iOS device + StoreKit sandbox
Purchase flow triggered from my Flutter app using Apple IAP
What happens
First purchase attempt works
My backend receives the confirmation
The album is granted correctly
On the second purchase attempt of the same consumable, I do not get a normal new purchase flow
Instead, StoreKit returns the product as restored
My app then cancels the attempt because a restored transaction arrived during checkout
Expected behavior
Because this product is a consumable, each purchase attempt should behave like a new purchase and allow the user to buy it again.
Actual behavior
On the second attempt, the transaction update comes back as restored instead of a new successful consumable purchase.
Relevant logs
First successful purchase:
[ProPurchasePage] ✅ Pay tapped. starting=false iap=true albumProd=album.credit.v2 proProd=pro.monthly
[IAP] update: id=album.credit.v2 status=PurchaseStatus.restored pendingComplete=false err=null
[IAP] expected=album.credit.v2 starting=true appleFlow=true
[ProPurchasePage] album credit success status=PurchaseStatus.restored receiptLen=5334
[AppleIapService] Sending Apple IAP confirmation for albumId=ariie_west_pretty_girl_summer, buyerUid=PYjgu9TMCieCVDLIdTuawY5k4Ay2
[AppleIapService] appleIapConfirm response status: 200
[AppleIapService] appleIapConfirm applied for albumId=ariie_west_pretty_girl_summer buyerUid=PYjgu9TMCieCVDLIdTuawY5k4Ay2
After that, the purchase is written correctly on my side:
"libraryAlbums": [
{
"AlbumId": "ariie_west_pretty_girl_summer",
"paid": true,
"Quantity": 1
}
]
Second and later attempts:
[ProPurchasePage] ✅ Pay tapped. starting=false iap=true albumProd=album.credit.v2 proProd=pro.monthly
[ProPurchasePage] buyConsumable (album.credit.v2) returned: true
[IAP] update: id=album.credit.v2 status=PurchaseStatus.restored pendingComplete=false err=null
[IAP] expected=album.credit.v2 starting=true appleFlow=true
[IAP] restored arrived during album checkout — cancelling attempt
Question
Is this expected StoreKit sandbox behavior for a consumable, or does this suggest:
a StoreKit sandbox issue,
a problem with how the product is configured in App Store Connect,
or a transaction-handling issue in the app/plugin layer?
Also, is there any Apple-recommended handling for repeated consumable purchases when sandbox keeps surfacing a restored status?
Topic:
App & System Services
SubTopic:
StoreKit
I currently have a schema in production (cloudKit and local files) containing non-optional transformable values, e.g.
@Attribute(.transformable(by: TestTransformer.self))
var number: TestTransformable = TestTransformable.init(value: 100)
Unfortunately, this is preventing any migration from succeeding (documented at length in FB22151570).
Briefly summarized, any migration from a Schema containing non-optional transformable values fails between willMigrate and didMigrate with the error "Can't find model for source store". This occurs for all migrations, including lightweight with a migration plan, lightweight without a plan, and custom migrations. Worst of all, this also prevents migration to optional transformable values, or the elimination of the transformable value entirely, leaving us completely stuck.
(note: optional transformable values only work when they have a default value set to nil, otherwise even these have issues migrating)
We already have features being blocked by this issue, and would like to preserve user-data while restoring our ability to move forwards with database.
Are there any known workarounds for using SwiftData (+CloudKit) when schema migration is non-operational?
We are launching a new app with a subscription in-app purchase (IAP).
The Status of the IAP is "Waiting for Review". We want to submit the app to app for review, but the section to select an IAP with the app is not appearing. According to online sources, if we submit a new app for review, without selecting the IAP that goes with it, then the app may be released in the App Store without users being able to purchase the IAP. This actually happened to us years ago and I can't remember how we got around it, but it was painful. It seems strange that Apple would allow this problem to persist for years. Why not just hire an intern to fix it? Maybe because they are too busy running around in circles at the new spaceship headquarters.
Regardless, our IAP has been sitting in "Waiting for Review" status for a while now and I'm concerned it may never be approved.
Any advice would be appreciated.