I'm developing a VoIP app.
Currently, I'm using CallKit to control call acceptance, and end-of-call processing.
When a call comes in while using the phone, CallKit appears as a banner at the top of the screen.
When I click "Accept" on the banner, the app opens and the call is received. (For OEMs, clicking the "Accept" button in the banner will accept the call as is.)
The reason this feature is needed is, for example, when a call comes in as a banner call while using a navigation app, accepting the call causes the navigation app to go to the back and the VoIP app to come to the foreground, causing inconvenience to customers. This needs to be improved.
Please advise.
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
Title
iOS App detecting external USB mass storage connection without user interaction
Background
We are developing an iOS application that connects to an action camera device via Bluetooth and Wi-Fi for control and data transfer.
In addition to wireless connectivity, our product requirements include supporting USB Mass Storage mode, where the camera (or a generic USB flash drive) is connected to an iPhone using a Lightning / USB-C adapter and appears in the Files app as an external drive.
Requirement
Our app needs to detect when an external USB mass storage device is connected or disconnected, with the following constraints:
The app is already running in the foreground
No user interaction is performed (no button tap, no document picker, no import UI)
The USB device can be:
A generic USB flash drive
An empty USB drive (no photos or videos)
The app only needs to know:
Whether an external USB storage device has been connected or removed
No need to access device identity, vendor info, or low-level USB details
The expected behavior is simply to update the app’s internal state or UI when a USB storage device becomes available.
Investigation Performed
We have already investigated and tested the following public and documented approaches, all of which did not provide a reliable or any notification for USB mass storage insertion:
ExternalAccessory / MFi
Not applicable for generic USB storage devices
Darwin notifications / CoreFoundation
Using notify_register_dispatch and CFNotificationCenterGetDarwinNotifyCenter
System USB / storage related notifications do not fire for third-party apps
File system APIs
NSFileManager mountedVolumeURLsIncludingResourceValuesForKeys
On iPhone, external USB drives visible in the Files app are not exposed as mounted volumes to third-party apps
FileProvider / DocumentPicker
Only provides access after explicit user interaction
No background or passive notification of availability
ImageCaptureCore
Limited to PTP camera devices
Does not apply to generic USB mass storage
Based on our testing, none of the public APIs provide a way to detect USB mass storage insertion automatically without user interaction.
Question to Apple
We would like to confirm the official platform behavior and capability boundary:
Is there any public, documented, App Store–approved API on iOS that allows a third-party app to be notified when a generic USB mass storage device is connected or disconnected, without user interaction?
If not:
Is this limitation intentional by platform design?
Is the recommended approach to rely exclusively on user-initiated document access flows (e.g. document picker, import UI)?
Are there any recommended best practices for apps that need to update their UI or internal state based on the availability of external USB storage devices?
Our goal is to ensure that our implementation fully complies with iOS platform guidelines and App Store Review requirements.
Environment
iOS versions tested: iOS 18 (latest public release)
Devices: iPhone models with Lightning / USB-C
USB devices: generic USB flash drives (including empty drives)
Closing
We appreciate clarification on whether this capability is intentionally restricted on iOS and how Apple recommends designing user experience around external USB storage access.
Thank you for your guidance.
Topic:
App & System Services
SubTopic:
Hardware
We have a simple function that retrieves users list via CSIdentityQueryCreate() and CSIdentityQueryExecute().
However, sometimes we get crashes in "com.apple.opendirectory.odxpc.xpc" queue and address sanitizer reports that something inside opendirectory related framework tries to access data that was released:
==327==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000166890010 at pc 0x000109b51f98 bp 0x00016b6f58d0 sp 0x00016b6f5070
READ of size 5 at 0x000166890010 thread T242
#0 0x000109b51f94 in memcpy+0x294 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x85f94)
#1 0x000191c08e64 in __CFStringCreateImmutableFunnel3+0x4f8 (CoreFoundation:arm64e+0x2e64)
#2 0x000191d2494c in ____CFBinaryPlistCreateObjectFiltered_block_invoke+0xa4 (CoreFoundation:arm64e+0x11e94c)
#3 0x000191c39fc8 in __CFBinaryPlistCreateObjectFiltered+0x698 (CoreFoundation:arm64e+0x33fc8)
#4 0x000191c3aff0 in __CFBinaryPlistCreateObjectFiltered+0x16c0 (CoreFoundation:arm64e+0x34ff0)
#5 0x000191c20b98 in __CFTryParseBinaryPlist+0xe8 (CoreFoundation:arm64e+0x1ab98)
#6 0x000191d11e14 in _CFPropertyListCreateWithData+0x98 (CoreFoundation:arm64e+0x10be14)
#7 0x000191c20a2c in CFPropertyListCreateWithData+0x38 (CoreFoundation:arm64e+0x1aa2c)
#8 0x00019b3a49d0 in ___odxpc_create_connection_block_invoke+0x104 (CFOpenDirectory:arm64e+0x29d0)
#9 0x00019189e82c in _xpc_connection_call_event_handler+0x6c (libxpc.dylib:arm64e+0xe82c)
#10 0x00019189d128 in _xpc_connection_mach_event+0x4a8 (libxpc.dylib:arm64e+0xd128)
#11 0x0001919f98a0 in _dispatch_client_callout4+0xc (libdispatch.dylib:arm64e+0x1b8a0)
#12 0x0001919fc10c in _dispatch_mach_msg_invoke+0x1cc (libdispatch.dylib:arm64e+0x1e10c)
#13 0x0001919e81b4 in _dispatch_lane_serial_drain+0x148 (libdispatch.dylib:arm64e+0xa1b4)
#14 0x0001919fce70 in _dispatch_mach_invoke+0x1d4 (libdispatch.dylib:arm64e+0x1ee70)
#15 0x0001919e81b4 in _dispatch_lane_serial_drain+0x148 (libdispatch.dylib:arm64e+0xa1b4)
#16 0x0001919e8e28 in _dispatch_lane_invoke+0x180 (libdispatch.dylib:arm64e+0xae28)
#17 0x0001919f3260 in _dispatch_root_queue_drain_deferred_wlh+0x120 (libdispatch.dylib:arm64e+0x15260)
#18 0x0001919f2ae4 in _dispatch_workloop_worker_thread+0x218 (libdispatch.dylib:arm64e+0x14ae4)
#19 0x000191b93e1c in _pthread_wqthread+0x120 (libsystem_pthread.dylib:arm64e+0x2e1c)
#20 0x000191b92b70 in start_wqthread+0x4 (libsystem_pthread.dylib:arm64e+0x1b70)
0x000166890010 is located 10946 bytes after 789838-byte region [0x0001667cc800,0x00016688d54e)
freed by thread T240 here:
#0 0x000109b09480 in free+0x7c (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3d480)
#1 0x000191c25ca8 in __CFDataDeallocate+0x5c (CoreFoundation:arm64e+0x1fca8)
#2 0x000191d56940 in _CFRelease+0x124 (CoreFoundation:arm64e+0x150940)
#3 0x00019f8e4540 in DSIdentity::~DSIdentity()+0x80 (OSServices:arm64e+0xe540)
#4 0x00019f8e45ec in DSUserIdentity::~DSUserIdentity()+0xc (OSServices:arm64e+0xe5ec)
#5 0x000191d56940 in _CFRelease+0x124 (CoreFoundation:arm64e+0x150940)
#6 0x000191c21b28 in __CFBasicHashDrain+0x1a8 (CoreFoundation:arm64e+0x1bb28)
#7 0x000191d56940 in _CFRelease+0x124 (CoreFoundation:arm64e+0x150940)
#8 0x00019f8ec1bc in DSIdentityQuery::~DSIdentityQuery()+0x88 (OSServices:arm64e+0x161bc)
#9 0x00019f8ec220 in DSIdentityQuery::~DSIdentityQuery()+0xc (OSServices:arm64e+0x16220)
#10 0x000191d56940 in _CFRelease+0x124 (CoreFoundation:arm64e+0x150940)
#11 0x000107eda344 in eka::posix::memory::CFReleaseDeleter<__CSIdentityQuery*>::operator()(__CSIdentityQuery*) const+0x3c (libxxx.dylib:arm64+0x9a344)
#12 0x000107eda1c8 (libxxx.dylib:arm64+0x9a1c8)
#13 0x000107eda010 (libxxx.dylib:arm64+0x9a010)
#14 0x000107e43424 (libx.dylib:axxrm64+0x3424)
#15 0x000107e41cc4 in my::helper::EnumerateUsers(std::__1::function<void (my::helper::UserInfo&&, bool&)> const&, unsigned int)+0xf7c (libxxx.dylib:arm64+0x1cc4)
...
previously allocated by thread T240 here:
#0 0x000109b0938c in malloc+0x78 (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x3d38c)
#1 0x0001919b39d4 in _malloc_type_malloc_outlined+0x60 (libsystem_malloc.dylib:arm64e+0x1d9d4)
#2 0x000191d11c34 in __CFDataInit+0x214 (CoreFoundation:arm64e+0x10bc34)
#3 0x00019f8e3228 in DSIdentityRecord::addJPEGData(char const*, unsigned int, unsigned int)+0x28 (OSServices:arm64e+0xd228)
#4 0x00019f8e627c in DSIdentity::CreateIdentityFromDSAttributeList(__CFAllocator const*, unsigned int, tDataBuffer*, unsigned int, long, bool, DSIdentityAuthority&, tDirStatus*)+0x1c8 (OSServices:arm64e+0x1027c)
#5 0x00019f8ecb64 in DSIdentityQuery::consumeRecordData(unsigned int, tDataBuffer*, long)+0xb4 (OSServices:arm64e+0x16b64)
#6 0x00019f900e2c in findRecordsWithNames+0xd0 (OSServices:arm64e+0x2ae2c)
#7 0x00019f8ec49c in DSIdentityQuery::performQuery(__CFError**)+0x1c4 (OSServices:arm64e+0x1649c)
#8 0x00019f8ec5c4 in DSIdentityQuery::execute(unsigned long, __CFError**)+0x40 (OSServices:arm64e+0x165c4)
#9 0x00019f8e06f4 in CSIdentityQueryExecute+0x2c (OSServices:arm64e+0xa6f4)
#10 0x000107e4144c in my::helper::EnumerateUsers(std::__1::function<void (my::helper::UserInfo&&, bool&)> const&, unsigned int)+0x704 (libxxx.dylib:arm64+0x144c)
EnumerateUsers is our function which basically does this (simplified, error checking skipped):
unique_cfref<CSIdentityQueryRef> query(CSIdentityQueryCreate(kCFAllocatorDefault, kCSIdentityClassUser, CSGetLocalIdentityAuthority()));
CSIdentityQueryExecute(query.get(), 0, &error);
unique_cfref<CFArrayRef> userIdentities(CSIdentityQueryCopyResults(query.get()));
auto userIdentitiesCount = CFArrayGetCount(userIdentities.get());
for (CFIndex i = 0; i < userIdentitiesCount; ++i)
{
// do something including calling getpwuid()
}
unique_cfref is just a std::unique_ptr wrapper that calls CFRelease when we goes out of scope.
Looks like something in OpenDirectory tries to access released data (weak references and delayed processing?). The problem seems to occur on macOS 15.
Is there any bug/regression, should we file a feedback? Or maybe we do something wrong?
Topic:
App & System Services
SubTopic:
Core OS
The documentation for isEligibleForAgeFeatures states:
Use this property to determine whether a person using your app is in an applicable region that requires additional age-related obligations for when you distribute apps on the App Store.
But what does "region" mean?
Is this going to return true if the user has downloaded the app from the US App Store? Or will it go further and geolocate the user and identify them as being within a particular relevant state within the US?
I've encountered an issue where we need multiple domain associations with separate Apple Pay implementations.
Briefly, we have a /.well-known/apple-developer-merchantid-domain-association already setup with Stripe, and now we need another, different version of the file to get setup with FreedomPay. FreedomPay insists this file represents a three-way relationship between all parties and I have no reason to disbelieve them.
I'm wondering if anyone has encountered this or if there is a standard procedure. I'm currently trying to find documentation on the exact way Apple Pay verification interacts with this file to see if we can produce it dynamically.
We recently released an update to our app to prepare for TX SB2420.
Almost immediately on release, we started getting crash reports of crashes when calling isEligibleForAgeFeatures.
Crashed: com.apple.root.user-initiated-qos.cooperative
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000004
Is it possible that these are beta users that have IOS 26.2 RC or is there a bug in the release version of IOS 26.2?
Note: The crash reports are coming from Crashlytics so we are not getting OS build identifiers other than version "26.2"
I have a total of 100 asset packs associated with my app but I have archived 5 of them. Unfortunately I am now unable to upload any more asset packs (the reported error is "backgroundAsset limit reached -- This app has already reached the maximum number of active backgroundAssets. Maximum allowed is 100.") I assumed that archiving asset packs would make them inactive (and thus not count against the limit). This seems to not be the case and I'm not sure how I can upload new asset packs.
We are integrating Apple’s DeclaredAgeRange SDK. To comply with relevant regulatory requirements, our understanding is as follows:
The app is only required to obtain the declared age range for users located in Texas.
For users outside of Texas, we should not proactively request age range information.
Accordingly, we would like to confirm the following:
Are we required to present the age range request prompt to all users in the United States?
If yes, we are concerned that this may significantly impact the overall user experience.
If it is permissible to request age range only for Texas users, how can we reliably determine whether a user is located in Texas on the client side?
For example, does Apple provide an API or recommended method for accurately identifying a user’s region (specifically Texas)?
I am trying to port my sandboxed macOS app completely over to iOS using a Catalyst target and SwiftUI.
There appears to be an issue when trying to drag to the Finder in Catalyst (and in SwiftUI in General). For some reason, the Finder will not accept multiple file drops, only a single file.
On my macOS (non-Catalyst AppKit target), I overcame this by dropping multiple files to a UTType of .folder, and the OS accepted the folder. This workaround is not available for iOS because .folder is a macOS-only option.
I have a test app to illustrate the issue. Hopefully someone can help.
Download Test App
Topic:
App & System Services
SubTopic:
General
Problem description
Since macOS Sequoia, our users have experienced issues with multicast traffic in our macOS app. Regularly, the app starts but cannot receive multicast, or multicast eventually stops mid-execution. The app sometimes asks again for Local Network permission, while it was already allowed so. Several versions of our app on a single machine are sometimes (but not always) shown as different instances in the System Settings > Privacy & Security > Local Network list. And when several instances are shown in that list, disabling one disables all of them, but it does not actually forbids the app from receiving multicast traffic. All of those issues are experienced by an increasing number of users after they update their system from macOS 14 to macOS 15 or 26, and many of them have reported networking issues during production-critical moments.
We haven't been able to find the root cause of those issues, so we built a simple test app, called "FM Mac App Test", that can reproduce multicast issues. This app creates a GCDAsyncUdpSocket socket to receive multicast packets from a piece of hardware we also develop, and displays a simple UI showing if such packets are received. The app is entitled with "Custom Network Protocol", is built against x86_64 and arm64, and is archived (signed and notarized). We can share the source code if requested.
Out of the many issues our main app exhibits, the test app showcases some:
The app asks several times for Local Network permission, even after being allowed so previously. After allowing the app's Local Network and rebooting the machine, the System Settings > Privacy & Security > Local Network does not show the app, and the app asks again for Local Network access.
The app shows a different Local Network Usage Description than in the project's plist.
Several versions of the app appear as different instances in the Privacy list, and behave strangely. Toggling on or off one instance toggles the others. Only one version of the app seems affected by the setting, the other versions always seem to have access to Local Network even when the toggle is set to off.
We even did see messages from different app versions in different user accounts. This seems to contradicts Apple's documentation that states user accounts have independent Privacy settings.
Can you help us understand what we are missing (in terms of build settings, entitlements, proper archiving...) so our app conforms to what macOS expects for proper Local Network behavior?
Related material
Local Network Privacy breaks Application: this issue seemed related to ours, but the fix was to ensure different versions of the app have different UUIDs. We ensured that ourselves, to no improvement.
Local Network FAQ
Technote TN3179
Steps to Reproduce
Test App is developed on Xcode 15.4 (15F31d) on macOS 14.5 (23F79), and runs on macOS 26.0.1 (25A362). We can share the source code if requested.
On a clean install of macOS Tahoe (our test setup used macOS 26.0.1 on a Mac mini M2 8GB), we upload the app (version 5.1).
We run the app, make sure the selected NIC is the proper one, and open the multicast socket. The app asks us to allow Local Network, we allow it. The alert shows a different Local Network Usage Description than the one we set in our project's plist.
The app properly shows packets are received from the console on our LAN.
We check the list in System Settings > Privacy & Security > Local Network, it includes our app properly allowed.
We then reboot the machine. After reboot, the same list does not show the app anymore.
We run the app, it asks again about Local Network access (still with incorrect Usage Description). We allow it again, but no console packet is received yet. Only after closing and reopening the socket are the console packets received.
After a 2nd reboot, the System Settings > Privacy & Security > Local Network list shows correctly the app. The app seems to now run fine.
We then upload an updated version of the same app (5.2), also built and notarized. The 2nd version is simulating when we send different versions of our main app to our users. The updated version has a different UUID than the 1st version.
The updated version also asks for Local Network access, this time with proper Usage Description.
A 3rd updated version of the app (5.3, also with unique UUID) behaves the same. The System Settings > Privacy & Security > Local Network list shows three instances of the app.
We toggle off one of the app, all of them toggle off. The 1st version of the app (5.1) does not have local network access anymore, but both 2nd and 3rd versions do, while their toggle button seems off.
We toggle on one of the app, all of them toggle on. All 3 versions have local network access.
Hi there,
We have been trying to set up URL filtering for our app but have run into a wall with generating the bloom filter.
Firstly, some context about our set up:
OHTTP handlers
Uses pre-warmed lambdas to expose the gateway and the configs endpoints using the javascript libary referenced here - https://developers.cloudflare.com/privacy-gateway/get-started/#resources
Status = untested
We have not yet got access to Apples relay servers
PIR service
We run the PIR service through AWS ECS behind an ALB
The container clones the following repo https://github.com/apple/swift-homomorphic-encryption, outside of config changes, we do not have any custom functionality
Status = working
From the logs, everything seems to be working here because it is responding to queries when they are sent, and never blocking anything it shouldn’t
Bloom filter generation
We generate a bloom filter from the following url list:
https://example.com
http://example.com
example.com
Then we put the result into the url filtering example application from here - https://developer.apple.com/documentation/networkextension/filtering-traffic-by-url
The info generated from the above URLs is:
{
"bits": 44,
"hashes": 11,
"seed": 2538058380,
"content": "m+yLyZ4O"
}
Status = broken
We think this is broken because we are getting requests to our PIR server for every single website we visit
We would have expected to only receive requests to the PIR server when going to example.com because it’s in our block list
It’s possible that behind the scenes Apple runs sporadically makes requests regardless of the bloom filter result, but that isn’t what we’d expect
We are generating our bloom filter in the following way:
We double hash the URL using fnv1a for the first, and murmurhash3 for the second
hashTwice(value: any, seed?: any): any {
return {
first: Number(fnv1a(value, { size: 32 })),
second: murmurhash3(value, seed),
};
}
We calculate the index positions from the following function/formula , as seen in https://github.com/ameshkov/swift-bloom/blob/master/Sources/BloomFilter/BloomFilter.swift#L96
doubleHashing(n: number, hashA: number, hashB: number, size: number): number {
return Math.abs((hashA + n * hashB) % size);
}
Questions:
What hashing algorithms are used and can you link an implementation that you know is compatible with Apple’s?
How are the index positions calculated from the iteration number, the size, and the hash results?
There was mention of a tool for generating a bloom filter that could be used for Apple’s URL filtering implementation, when can we expect the release of this tool?
(I truly appreciate all the responses you all have written for me :bow: )
I was under the assumption that for Live Activity, in order for you to be able to update the Activity, you need an update token. And for the OS to issue you the update token, user must hit the "Allow" from the lock screen.
However based on these screenshots it seems that you don't need to hit "Allow" to be able to update the Live Activity.
Live Activity was updated — even without the user hitting "Allow"
So now I'm wondering if:
Is hitting Allow required for the update token to get issued? Or that assumption is incorrect? In our tests (when connected to Proxyman, the OS emits the update token after user hits "Allow" / "Always Allow")
If you don't hit allow, are there alternate ways to update the Live Activity without having the update token?
I'm guessing you could set a short stale time and then when the OS launches the app in the background you query the server and then update the Live Activity. Is that a worthy approach?
I also noticed that the "The Philly Inquirer" App has 'Background App Refresh" enabled, but this happened in 2 minutes. In our architecture assessments, after reviewing Apple's docs on 'Background Processing", we didn't think of it as a viable option, because it can't guarantee if the OS is given time in the next 2 minutes or 10 hours later when the phone is getting charged again.
Are any of these workarounds viable or are there alternate approaches?
Our requirement is:
be able to use Live Activity between 2-72hrs after app install. (I mention this because perhaps Apple may impost some restrictions for new installs)
be able to update an active Live Activity within 1-2 minutes after it has began.
I'm developing a watchOS nap app that detects when the user falls asleep by monitoring heart rate changes.
== Technical Implementation ==
HKWorkoutSession (.mindAndBody) for background execution
HKAnchoredObjectQuery for real-time heart rate data
CoreMotion for movement detection
== Battery Considerations ==
Heart rate monitoring ONLY active when user explicitly starts a session
Monitoring continues until user is awakened OR 60-minute limit is reached
If no sleep detected within 60 minutes, session auto-ends
(user may have abandoned or forgotten to stop)
App displays clear UI indicating monitoring is active
Typical session: 15-30 minutes, keeping battery usage minimal
== The Problem ==
HKWorkoutSession affects Activity Rings during the session. Users receive
"Exercise goal reached" notifications while resting — confusing.
== What I've Tried ==
Not using HKLiveWorkoutBuilder → Activity Rings still affected
Using builder but not calling finishWorkout()
(per https://developer.apple.com/forums/thread/780220)
→ Activity Rings still affected
WKExtendedRuntimeSession (self-care type)
(per https://developer.apple.com/forums/thread/721077)
→ Only ~10 min runtime, need up to 60 min
HKObserverQuery + enableBackgroundDelivery
(per https://developer.apple.com/forums/thread/779101)
→ ~4 updates/hour, too slow for real-time detection
Audio background session for continuous processing
(suggested in https://developer.apple.com/forums/thread/130287)
→ Concerned about App Store rejection for non-audio app;
if official approves this technical route, I can implement in this direction
Some online resources mention "Health Monitoring Entitlement" from WWDC 2019
Session 251, but I could not find any official documentation for this entitlement.
Apple Developer Support also confirmed they cannot locate it?
== My Question ==
Is there any supported way to:
Monitor heart rate in background for up to 60 minutes
WITHOUT affecting Activity Rings or creating workout records?
If this requires a special entitlement or API access, please advise on
the application process. Or allow me to submit a code-level support request.
Any guidance would be greatly appreciated. Thank you!
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Entitlements
Health and Fitness
HealthKit
On iOS 18 and lower version, my application supports automatically switching to [System settings - Personal Hotspot] directly. But on iOS 26, my application will be redirected to [System settings- Apps].
Does iOS 26 disable the behavior of directly jumping to the system hotspot page? If support, could you share the API for iOS 26?
AgeRangeService is the burning topic right now. Needless to say, Everything is so unclear.
We got our app finally into the TestFlight for QA and the product to test. only to find out that AgeAssurance for sandbox testing does not work.
There is no document confirming or denying whether and when age assurance for the App with the release configuration in test flight would work.
There isn't any guidance from Apple on whether an app that sells physical goods, such as an e-commerce app, can continue doing business as usual.
Also, there is no clarity that the Age assurance options are off, 13, unverified, 13 verified, and so on.
How those should be used.
Topic:
App & System Services
SubTopic:
General
I am currently encountering a problem: during the process of uploading a large file, I have moved the file that was not successfully uploaded to the trash can. These two operations have been tested to be serial (triggering the 'create Item' callback first, followed by the 'modify Item' callback), which means that the file must be uploaded before it can be moved to the recycle bin (which can also result in the file being stored in the cloud recycle bin). I want to implement: directly interrupt this upload process and then do not complete the upload. How can I achieve this? Please help me. Thank you
We have developed a Parental/Self control app using Screen time API.
We have used individual authentication to authorize the app, using the instructions here:
https://developer.apple.com/documentation/familycontrols/authorizationcenter
The problem is , that individual auth can be disabled easily , by the following steps:
enter Settings app.
in Settings app, click on the Parental/Self control app.
click to disable screen time restriction.
show the device owner's face/fingerprint. (or pin code)
Why is that a problem:
Parental control apps, or self-control apps, are about giving control to the software, To make it hard for the user to disable the restrictions.
So using the flow I have introduced above, it's super-easy for a user to disable his Parental control restrictions, which misses the entire point of Parental/Self control idea.
Furthermore, not only the user have the means to unlock his screen time restrictions, he also MUST have the means to unlock it.
This makes Screen time (with individual auth) useless:
I have a code ready to make a great parental control app for my clients, with amazing ideas, but I can't use the Screen time API unless this problem is fixed.
Why child-parent auth is not enough:
My clients are grownups people between ages of 15-40, that are interested in self-control, so they don't have iCloud child accounts.
also, the child-parent auth solution forces my clients to give some control to other person, and my clients prefer their privacy. Some of them prefer self-control and not parental-control.
What I suggest as a solution:
1: Give more options to users how to disable the Screen time restrictions. including:
a second faceID / FingerPrint (that isn't the same as the one used to unlock the device)
a second pin password.
a string password
2: Give the users the option to choose to not have the device's owner Face/Finger/Pincode ID , as a method to disable the Screen time restrictions.
I am using the MatterSupport extension to commission devices for my own ecosystem. I use the extension to do the initial connection to the device (BLE, PASE, bring device onto wifi/thread) and then use the method
commissionDevice(in home: MatterAddDeviceRequest.Home?, onboardingPayload: String, commissioningID: UUID)
in MatterAddDeviceExtensionRequestHandler to send a request to my own hub on the local network where it then connects to the device via wifi/thread and fully commissions the device. This flow is working correctly for wifi enabled devices, however it fails for thread devices. For some context, I am using my own border router (and have already added the router's credentials to the phone using THClient's storeCredentials). Here are some device-specific results:
ESP32 (WIFI): successful commission
ESP32 (THREAD): failure
Matter Certified ONVIS smart plug (THREAD): failure
The ESP32's are running espressif matter examples.
Example border router is a running OTBR docker container
I believe that the entire PASE session is established and the device gets onto the thread network, but the process seems to stall after that. I have verified that selectThreadNetwork(...) and validateDeviceCredential(...) get called but the commissioning process seems to stall before it can get to commissionDevice(...)
I am limited to 7k characters, but I'll try to include as many relevant log lines as I can near the error if anyone has any ideas. I've already created a bug report with ID: FB18985348 which includes the full logs from the esp32 and a sysdiagnose from an iPhone 12 Pro (iOS 18.5) using the following log profiles:
Home app/HomeKit
HomeThread
ThreadNetwork
When commissioning directly from my hub, the entire commissioning completes successfully 100% of the time. This failure only happens when I use MatterSupport to initiate commissioning for Matter over Thread devices specifically.
Very condensed homed log overview for uncertified ESP32 thread example
Next: 'SecurePairing' -> 'ReadCommissioningInfo'
Step: 'ReadCommissioningInfo'
Sending read requests for commissioning information
NetworkCommissioning Features: has Thread. endpointid = 0
<MTRDeviceController_Concrete: ..., uuid: F9BB9F53-BF73-4B82-B00B-045E7709530E...> completed for nodeID 0x0000000055d193ec with status: Success
✔ 'ReadCommissioningInfo'
Next: 'ReadCommissioningInfo' -> 'ArmFailSafe'
Step: 'ArmFailSafe'
✔ 'ArmFailSafe'
Next: 'ArmFailSafe' -> 'ConfigRegulatory'
Step: 'ConfigRegulatory'
✔ 'ConfigRegulatory'
Next: 'ConfigRegulatory' -> 'ConfigureTCAcknowledgments'
Step: 'ConfigureTCAcknowledgments'
✔ 'ConfigureTCAcknowledgments'
Next: 'ConfigureTCAcknowledgments' -> 'SendPAICertificateRequest'
Step: 'SendPAICertificateRequest'
✔ 'SendPAICertificateRequest'
Next: 'SendPAICertificateRequest' -> 'SendDACCertificateRequest'
Step: 'SendDACCertificateRequest'
✔ 'SendDACCertificateRequest'
Next: 'SendDACCertificateRequest' -> 'SendAttestationRequest'
Step: 'SendAttestationRequest'
✔ 'SendAttestationRequest'
Next: 'SendAttestationRequest' -> 'AttestationVerification'
Step: 'AttestationVerification'
Error on commissioning step 'AttestationVerification': Internal error
Next: 'AttestationVerification' -> 'AttestationRevocationCheck'
Step: 'AttestationRevocationCheck' (with error)
Device attestation error: Integrity check failed.
Continue commissioning (ignore attestation failure: YES)
✔ 'AttestationRevocationCheck'
Next: 'AttestationRevocationCheck' -> 'SendOpCertSigningRequest'
Step: 'SendOpCertSigningRequest'
✔ 'SendOpCertSigningRequest'
Next: 'SendOpCertSigningRequest' -> 'ValidateCSR'
Step: 'ValidateCSR'
✔ 'ValidateCSR'
Next: 'ValidateCSR' -> 'GenerateNOCChain'
Step: 'GenerateNOCChain'
✔ 'GenerateNOCChain'
Step: 'SendTrustedRootCert'
✔ 'SendTrustedRootCert'
Next: 'SendTrustedRootCert' -> 'SendNOC'
Step: 'SendNOC'
✔ 'SendNOC'
Next: 'SendNOC' -> 'ThreadNetworkSetup'
Step: 'ThreadNetworkSetup'
✔ 'ThreadNetworkSetup'
Next: 'ThreadNetworkSetup' -> 'FailsafeBeforeThreadEnable'
Step: 'FailsafeBeforeThreadEnable'
✔ 'FailsafeBeforeThreadEnable'
Next: 'FailsafeBeforeThreadEnable' -> 'ThreadNetworkEnable'
Step: 'ThreadNetworkEnable'
✔ 'ThreadNetworkEnable'
Next: 'ThreadNetworkEnable' -> 'kEvictPreviousCaseSessions'
Step: 'kEvictPreviousCaseSessions'
✔ 'kEvictPreviousCaseSessions'
Next: 'kEvictPreviousCaseSessions' -> 'kFindOperationalForStayActive'
Step: 'kFindOperationalForStayActive'
Error: Timeout
Next: 'kFindOperationalForStayActive' -> 'Cleanup'
Step: 'Cleanup' (with timeout error)
✔ 'Cleanup'
Commissioning complete for node ID 0x0000000055D193EC with timeout error
Hi!
I have over 800 days strike in closing my move circle. However oerfect month badge is not popping up for November, we have now mid of Dec and still no update.
I updated iOS to 26, did multiple resets and hard resets and still no badge. I checked many forums and post but any of given tips is working in my case.
i know it sounds funny, but it’s frustrating that I’m not getting this little gold medal to keep me motivated 😅
does anyone know how to deal with it? Is it common issue?
I implemented BGContinuedProcessingTask in my app and it seems to be working well for everyone except one user (so far) who has reached out to report nothing happens when they tap the Start Processing button. They have an iPhone 12 Pro Max running iOS 26.1. Restarting iPhone does not fix it.
When they turn off the background processing feature in the app, it works. In that case my code directly calls the function to start processing instead of waiting for it to be invoked in the register block (or submit catch block).
Is this a bug that's possible to occur, maybe device specific? Or have I done something wrong in the implementation?
func startProcessingTapped(_ sender: UIButton) {
if isBackgroundProcessingEnabled {
startBackgroundContinuedProcessing()
} else {
startProcessing(backgroundTask: nil)
}
}
func startBackgroundContinuedProcessing() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: taskIdentifier, using: .main) { @Sendable [weak self] task in
guard self != nil else { return }
startProcessing(backgroundTask: task as? BGContinuedProcessingTask)
}
let request = BGContinuedProcessingTaskRequest(identifier: taskIdentifier, title: title, subtitle: subtitle)
request.strategy = .fail
if BGTaskScheduler.supportedResources.contains(.gpu) {
request.requiredResources = .gpu
}
do {
try BGTaskScheduler.shared.submit(request)
} catch {
startProcessing(backgroundTask: nil)
}
}
func startProcessing(backgroundTask: BGContinuedProcessingTask?) {
// FIXME: Never called for this user when isBackgroundProcessingEnabled is true
}