Description :
Our app helps users connect to Wi-Fi hotspots. We are trying to adapt our code to iOS 26 Hotspot Authentication and Hotspot Evaluation application extensions.
When filtering hotspots in the filterScanList callback, we need to fetch support information from a remote server to determine which hotspots are supported. However, attempts to use URLSession or NWTCPConnection in the extension always fail.
When accessing a URL (e.g., https://www.example.com), the network log shows:
Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found."
When accessing a raw IP address, the log shows:
[1: Operation not permitted]
Interestingly, NWPathMonitor shows the network path as satisfied, indicating that the network is reachable.
Question:
Are there any missing permissions or misconfigurations on our side, or are we using the wrong approach? Is there an official recommended way to perform network requests from an NEHotspotEvaluationProvider extension?
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I develop a Network Extension with NEFilterDataProvider and want to understand how to stop or disable it on exit of the base app without deactivating NE from OS and leave ability to start it again without requiring a password from the user.
It starts normally, but when I try to disable it:
NEFilterManager.sharedManager.enabled = NO;
[NEFilterManager.sharedManager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
// never called
}];
the completion handler has never called.
But stopFilterWithReason inside the NE code called by the framework where I only replay with required completionHandler();. Then NE process keeps alive.
I also tried to call remove, which should disable NE:
[NEFilterManager.sharedManager removeFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
// never called
}];
with same result - I freeze forever on waiting completion handler.
So what is the correct way to disable NE without explicit deactivation it by [OSSystemExtensionRequest deactivationRequestForExtension:...]?
Hello Apple Support Team,
We are experiencing a performance issue with HTTP/3 in our iOS application during testing.
Problem Description:
Network requests using HTTP/3 are significantly slower than expected. This issue occurs on both Wi-Fi and 4G networks, with both IPv4 and IPv6. The same setup worked correctly in an earlier experiment.
Key Observations:
The slowdown disappears when the device uses:
· A personal hotspot.
· Network Link Conditioner (with no limitations applied).
· Internet sharing from a MacBook via USB (where traffic was also inspected with Wireshark without issues).
The problem is specific to HTTP/3 and does not occur with HTTP/2.
The issue is reproducible on iOS 15, 18.7, and the latest iOS 26 beta.
HTTP/3 is confirmed to be active (via assumeHttp3Capable and Alt-Svc header).
Crucially, the same backend endpoint works with normal performance on Android devices and using curl with HTTP/3 support from the same network.
I've checked the CFNetwork logs in the Console but haven't found any suspicious errors or obvious clues that explain the slowdown.
We are using a standard URLSession with basic configuration.
Attempted to collect qlog diagnostics by setting the QUIC_LOG_DIRECTORY=~/ tmp environment variable, but the logs were not generated.
Question:
What could cause HTTP/3 performance to improve only when the device is connected through a hotspot, unrestricted Network Link Conditioner, or USB-tethered connection? The fact that Android and curl work correctly points to an issue specific to the iOS network stack. Are there known conditions or policies (e.g., related to network interface handling, QoS, or specific packet processing) that could lead to this behavior?
Additionally, why might the qlog environment variable fail to produce logs, and are there other ways to obtain detailed HTTP/3 diagnostic information from iOS?
Any guidance on further diagnostic steps or specific system logs to examine would be greatly appreciated.
Thank you for your assistance.
Satellite Communication framework, experiences a failure in receiving network path updates when a device transitions from Satellite to a fringe LTE area. The iOS Status Bar correctly updates to show "LTE," but our application does not receive the corresponding network path update (e.g., via NWPathMonitor). This leaves our app UI locked in "Satellite Mode," while the user sees "LTE" in the status bar, causing critical user confusion.
Feedback: FB20976940
Hi everyone,
I’ve run into a consistent issue on multiple Apple Vision Pro devices where downloads using URLSessionConfiguration.background are between 4× and 10x slower than when using URLSessionConfiguration.default. This issue is systematic and can easily be reproduced.
This only happens on device, in the simulator, both configurations download files at the expected speed with respect to the network speed.
Details:
Tested on visionOS 26.0.1 and 26.1 (public releases)
Reproduced across 2 Vision Pro (currently testing on a third one)
Reproduced on 2 different Wi-fi networks (50mb/s and 880mb/s)
From my tests this speed issue seems to affects multiple apps on my device: Stobo Vision (our app), Immersive India, Amplium
Not server-related (reproduces with Apple CDN, S3, and DigitalOcean)
I’ve built a small sample project that makes this easy to reproduce, it downloads a large file (1.1 GB video) using two managers:
One with URLSessionConfiguration.default
One with URLSessionConfiguration.background
You can also try it with your own file url (from an s3 for example)
Expected behavior:
Background sessions should behave similarly to default sessions in terms of throughput, just as they do in the simulator. To be clear I am comparing both config when running in the foreground, not in the background.
Actual behavior:
Background sessions on Vision Pro are significantly slower, making them less usable for large file downloads.
On this screenshot it's even reaching 27x slower than the expected speed. Default config takes ~97s to download and Background config takes ~2640s. I do now have the fastest internet connection but 44min to download 90.5MB is extremely slow.
Has anyone else seen this behavior or found a workaround? Or is this an expected behavior from URLSessionConfiguration.background? If I'm doing something wrong please let me know
Repo link:
https://github.com/stobo-app/DownloadConfigTesting
I spent the entire day debugging a network issue on my Apple Watch app, only to realize the problem isn't my code—it's Apple's inflexible design.
The Context:
I am building a generic MCP (Model Context Protocol) client for watchOS. The nature of this app is to allow users to input their own server URLs (e.g., a self-hosted endpoint, or public services like GitHub's MCP server) to interact with LLMs and tools.
The Problem:
When using standard URLSession to connect to widely trusted, public HTTPS endpoints (specifically GitHub's official MCP server at https://mcp.github.com), the connection is forcefully terminated by the OS with NSURLErrorDomain Code=-1200 (TLS handshake failed).
The Analysis:
This is caused by App Transport Security (ATS). ATS is enforcing a draconian set of security standards (specific ciphers, forward secrecy requirements, etc.) that many perfectly valid, secure, and globally accepted servers do not strictly meet 100%.
The Absurdity:
We cannot whitelist domains: Since this is a generic client, I cannot add NSExceptionDomains to Info.plist because I don't know what URL the user will input.
We cannot disable ATS: Adding NSAllowsArbitraryLoads is a guaranteed rejection during App Store review for a general-purpose app without a "compelling reason" acceptable to Apple.
The result: My app is effectively bricked. It cannot connect to GitHub. It cannot connect to 90% of the user's self-hosted servers.
The Question:
Is the Apple Watch just a toy? How does Apple expect us to build flexible, professional tools when the OS acts like a nanny that blocks connections to GitHub?
We need a way to bypass strict ATS checks for user-initiated connections in generic network tools, similar to how curl -k or other developer tools work. The current "all-or-nothing" policy is suffocating.
Following previous question here :https://developer.apple.com/forums/thread/801397, I've decided to move my VPN implementation using NEPacketTunnelProvider on a dedicated networkExtension.
My extension receives packets using readPacketsWithCompletionHandler and forwards them immediately to a daemon through a shared memory ring buffer with Mach port signaling. The daemon then encapsulates the packets with our VPN protocol and sends them over a UDP socket.
I'm seeing significant throughput degradation, much higher than the tunnel overhead itself. On our side, the IPC path supports parallel handling, but I'm not not sure whether the provider has any internal limitation that prevents packets from being processed in parallel. The tunnel protocol requires packet ordering, but preparation can be done in parallel if the provider allows it.
Is there any inherent constraint in NEPacketTunnelProvider that prevents concurrent packet handling, or any recommended approach to improve throughput in this model? For comparison, when I create a utun interface manually with ifconfig and route traffic through it, I observe performance that is about four times faster.
I am developing a program on my chip and attempting to establish a connection with the WiFi Aware demo app launched by iOS 26. Currently, I am encountering an issue during the pairing phase.
If I am the subscriber of the service and successfully complete the follow-up frame exchange of pairing bootstrapping, I see the PIN code displayed by iOS.
Question 1: How should I use this PIN code?
Question 2: Subsequently, I need to negotiate keys with iOS through PASN. What should I use as the password for the PASN SAE process?
If I am the subscriber of the service and successfully complete the follow-up frame exchange of pairing bootstrapping, I should display the PIN code.
Question 3: How do I generate this PIN code?
Question 4: Subsequently, I need to negotiate keys with iOS through PASN. What should I use as the password for the PASN SAE process?
Topic:
App & System Services
SubTopic:
Networking
We have a Java application built for macOS. On the first launch, the application prompts the user to allow local network access. We've correctly added the NSLocalNetworkUsageDescription key to the Info.plist, and the provided description appears in the system prompt.
After the user grants permission, the application can successfully connect to a local server using its hostname. However, the issue arises after the system is rebooted. When the application is launched again, macOS does not prompt for local network access a second time—which is expected, as the permission was already granted.
Despite this, the application is unable to connect to the local server. It appears the previously granted permission is being ignored after a reboot. A temporary workaround is to manually toggle the Local Network permission off and back on via System Settings > Privacy & Security, which restores connectivity—until the next reboot.
This behavior is highly disruptive, both for us and for a significant number of our users. We can reproduce this on multiple systems...
The issues started from macOS Sequoia 15.0
By opening the application bundle using "Show Package Contents," we can launch the application via "JavaAppLauncher" without any issues. Once started, the application is able to connect to our server over the local network. This seems to bypass the granted permissions? "JavaAppLauncher" is also been used in our Info.plist file
Hi there,
When running the app, I found on my Firebase Crashlytics, sometimes got error like this when using Wi-Fi:
Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50, _NSURLErrorNWResolutionReportKey=Resolved 0 endpoints in 1ms using unknown from cache, _NSURLErrorNWPathKey=unsatisfied (Denied over Wi-Fi interface), interface: utun6, ipv4, dns, uses wifi, LQM: unknown}
I've run through the threads, found this link, but I think this issue is different on the interface.
It would be great there is and idea how to troubleshoot this issue. Thank you.
Hello,
I’m developing a macOS application signed with a Developer ID (outside the App Store) that includes a Network Extension.
The app has been successfully notarized, and the network filter is registered, but the Network Extension itself remains inactive — it does not install or run properly.
It seems that the issue might be related to the entitlements configuration between the container app and the Network Extension target.
Could you please provide a detailed checklist for:
The required entitlements and configurations for the container app, and
The required entitlements and configurations for the Network Extension target?
Additionally, are there any specific Xcode settings that are mandatory for the Network Extension to be properly installed and activated on macOS when distributed via Developer ID?
Thank you in advance for your help.
Hello,
I’m developing a macOS application signed with a Developer ID (outside the App Store) that includes a Network Extension.
The app has been successfully notarized, and the network filter is registered, but the Network Extension itself remains inactive — it does not install or run properly.
It seems that the issue might be related to the entitlements configuration between the container app and the Network Extension target.
Could you please provide a detailed checklist for:
1.The required entitlements and configurations for the container app, and
2.The required entitlements and configurations for the Network Extension target?
Additionally, are there any specific Xcode settings that are mandatory for the Network Extension to be properly installed and activated on macOS when distributed via Developer ID?
Thank you in advance for your help.
I'm currently testing URLFilter for use in a macOS product. After calling loadFromPreferences, I set the following configuration parameters:
pirServerURL = URL(string: "http://localhost:8080")!
pirAuthenticationToken = "AAAA"
controlProviderBundleIdentifier = "{extension app bundle identifier}"
However, when I call saveToPreferences, I get an Invalid Configuration error.
Is there a way to determine which parameter is invalid or incorrectly set?
Also, I would appreciate any macOS-specific examples of using NEURLFilterManager, as most of the documentation I’ve found seems to focus on iOS.
Thank you.
Title:
iPhone 17 Wi-Fi connection via NEBOTspotConfigurationManager::applyConfiguration is significantly slower compared to other models
Description:
When using the NEBOTspotConfigurationManager::applyConfiguration API to connect to a Wi-Fi network, the connection process on iPhone 17 is extremely slow compared to other iPhone models.
For example, in one test case:
The API call to connect to Wi-Fi (LRA-AN00%6149%HonorConnect) was initiated at 16:16:29.
However, the Association Request was not actually initiated until 16:16:58.
During this ~29-second delay, the device appears to be scanning before starting the association process.
This issue is specific to iPhone 17 — the same code and network environment do not exhibit this delay on other iPhone models.
Steps to Reproduce:
On an iPhone 17, call NEBOTspotConfigurationManager::applyConfiguration to connect to a known Wi-Fi network.
Observe the timestamps between API invocation and the start of the Association Request.
Compare with the same process on other iPhone models.
Expected Result:
The Association Request should start almost immediately after the API call, similar to other iPhone models.
Actual Result:
On iPhone 17, there is a ~29-second delay between API call and Association Request initiation, during which the device appears to be scanning.
Impact:
This delay affects user experience and connection performance when using programmatic Wi-Fi configuration on iPhone 17.
Environment:
Device: iPhone 17
iOS Version:26.0.1
API: NEBOTspotConfigurationManager::applyConfiguration
Network: WPA2-Personal
IOS.txt
Hello,
I have a peer to peer networking setup in my app that uses Network Framework with Bonjour and QUIC via NWBrowser, NWListener, NWConnection, and NWEndpoint and all works as expected.
I watched the videos about the new iOS 26 Networking stuff (NetworkBrowser, NetworkListener, NetworkConnection) and wanted to try and migrate all my code to use the the new APIs (still use Bonjour and NOT use Wi-Fi Aware) but hit some issues. I was following how the Wi-Fi Aware example app was receiving messages
for try await messageData in connection.messages {
but when I got things setup with QUIC in a similar fashion I got the following compile error
Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Copyable'
Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Escapable'
Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Copyable'
Requirement from conditional conformance of '(content: QUIC.ContentType, metadata: QUIC.Metadata)' to 'Escapable'
When I asked Cursor about what I was facing its response was as follows: "The connection.messages stream changed in the new Network APIs: it now yields typed (content, metadata) tuples. Iterating with for try await incoming in connection.messages asks the compiler to conform that tuple to Copyable/Escapable; for QUIC the tuple isn’t copyable, so you hit the conditional-conformance error."
I am curious if you've been able to use the new iOS 26 network APIs with QUIC?
Thank you,
Captadoh
Hello,
I have searched here on the forums for "WiFi Aware" and have read through just about every post. In a lot of them the person says they were able to get the example app https://developer.apple.com/documentation/wifiaware/building-peer-to-peer-apps working with their iOS devices. I, for some reason, am not able to get the example app to fully work.
I am able to build the app and load the app onto two physical iPhone 12 minis (both are running iOS 26.0.1). I follow the steps shown at the link share above but I get stuck because I can't get past the "enter this pin code to connect" step. I make one device be a host of a simulation and the other device the viewer of a simulation. On each device I tap the "+" button. On the viewer device I tap the discovered device. On the host device I then see the pin. I then enter the pin on the viewer device. After this step nothing happens. My only choice on the viewer device is to tap "cancel" and exit the "enter the pin step". If I go into the actual device settings (Settings -> Privacy & Security -> Paired Devices) I see that the devices are "paired" but the app doesn't seem to think so.
Are there some special settings I need to turn on for the app to work properly?
In an attempt to figure out what was going wrong I took the example app and paired it down to just send back simple messages based on user button taps.
These are my logs from when I start up the app and start one device as the hoster and one as the viewer.
Selected Mode: Hoster
Start NetworkListener
[L1 ready, local endpoint: <NULL>, parameters: udp, traffic class: 700, interface: nan0, local: ::.0, definite, attribution: developer, server, port: 62182, path satisfied (Path is satisfied), interface: nan0[802.11], ipv4, uses wifi, LQM: unknown, service: com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J._sat-simulation._udp scope:0 route:0 custom:107]: waiting(POSIXErrorCode(rawValue: 50): Network is down)
[L1 ready, local endpoint: <NULL>, parameters: udp, traffic class: 700, interface: nan0, local: ::.0, definite, attribution: developer, server, port: 62182, path satisfied (Path is satisfied), interface: nan0[802.11], ipv4, uses wifi, LQM: unknown, service: com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J._sat-simulation._udp scope:0 route:0 custom:107]: ready
[L1 failed, local endpoint: <NULL>, parameters: udp, traffic class: 700, interface: nan0, local: ::.0, definite, attribution: developer, server, port: 62182, path satisfied (Path is satisfied), interface: nan0[802.11], ipv4, uses wifi, LQM: unknown, service: com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J._sat-simulation._udp scope:0 route:0 custom:107]: failed(-11992: Wi-Fi Aware)
nw_listener_cancel_block_invoke [L1] Listener is already cancelled, ignoring cancel
nw_listener_cancel_block_invoke [L1] Listener is already cancelled, ignoring cancel
nw_listener_cancel_block_invoke [L1] Listener is already cancelled, ignoring cancel
Networking failed: -11992: Wi-Fi Aware
Error acquiring assertion: <Error Domain=RBSAssertionErrorDomain Code=2 "Could not find attribute name in domain plist" UserInfo={NSLocalizedFailureReason=Could not find attribute name in domain plist}>
<0x105e35400> Gesture: System gesture gate timed out.
Selected Mode: Viewer
Start NetworkBrowser
[B1 <nw_browse_descriptor application_service _sat-simulation._udp bundle_id=com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J device_types=7f device_scope=ff custom:109>, generic, interface: nan0, attribution: developer]: ready
nw_browser_update_path_browser_locked Received browser Wi-Fi Aware
nw_browser_cancel [B1] The browser has already been cancelled, ignoring nw_browser_cancel().
[B1 <nw_browse_descriptor application_service _sat-simulation._udp bundle_id=com.example.apple-samplecode.Wi-FiAwareSample8B4DX93M9J device_types=7f device_scope=ff custom:109>, generic, interface: nan0, attribution: developer]: failed(-11992: Wi-Fi Aware)
nw_browser_cancel [B1] The browser has already been cancelled, ignoring nw_browser_cancel().
Networking failed: -11992: Wi-Fi Aware
Error acquiring assertion: <Error Domain=RBSAssertionErrorDomain Code=2 "Could not find attribute name in domain plist" UserInfo={NSLocalizedFailureReason=Could not find attribute name in domain plist}>
This guy stands out to me Networking failed: -11992: Wi-Fi Aware but I can't find any info on what it means.
Thank you
I’m building a Personal VPN app (non-MDM) that uses a NEPacketTunnelProvider extension for content filtering and blocking.
When configuring the VPN locally using NETunnelProviderManager.saveToPreferences, the call fails with:
Error Domain=NEConfigurationErrorDomain Code=10 "permission denied"
Error Domain=NEVPNErrorDomain Code=5 "permission denied"
The system does prompt for VPN permission (“Would Like to Add VPN Configurations”), but the error still occurs after the user allows it.
Setup:
• Main App ID – com.promisecouple.app
• Extension ID – com.promisecouple.app.PromiseVPN
• Capabilities – App Group + Personal VPN + Network Extensions
• Main app entitlements:
com.apple.developer.networking.vpn.api = allow-vpn
com.apple.developer.networking.networkextension = packet-tunnel-provider
• Extension entitlements: same + shared App Group
Problem:
• If I remove the networkextension entitlement, the app runs locally without the Code 5 error.
• But App Store Connect then rejects the build with:
Missing Entitlement: The bundle 'Promise.app' is missing entitlement 'com.apple.developer.networking.networkextension'.
Question:
What is the correct entitlement configuration for a Personal VPN app using NEPacketTunnelProvider (non-MDM)?
Is com.apple.developer.networking.networkextension required on the main app or only on the extension?
Why does including it cause saveToPreferences → Code 5/10 “permission denied” on device?
Environment:
Xcode 26.1 (17B55), iOS 17.3+ on physical device (non-MDM)
Both provisioning profiles and certificates are valid.
We’re implementing VPN application using the WireGuard protocol and aiming to support both split-tunnel and per-app VPN configurations. Each mode works correctly on its own: per-app VPN functions well when configured with a full tunnel and split-tunnel works as expected when per-app is disabled.
However, combining both configurations leads to issues. Specifically, the routing table is not set up properly, resulting in traffic that should not be routed through the tunnel is routed through the tunnel.
Detailed description:
Through our backend, we are pushing these two plist files to the iPad one after the other:
VPN config with allowed IPs 1.1.1.1/32
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Inc//DTD PLIST 1.0//EN" http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
<key>PayloadUUID</key>
<string>3fd861df-c917-4716-97e5-f5e96452436a</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadOrganization</key>
<string>someorganization</string>
<key>PayloadIdentifier</key>
<string>config.11ff5059-369f-4a71-afea-d5fdbfa99c91</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadDisplayName</key>
<string> test</string>
<key>PayloadDescription</key>
<string>(Version 13) </string>
<key>PayloadRemovalDisallowed</key>
<true />
<key>PayloadContent</key>
<array>
<dict>
<key>VPN</key>
<dict>
<key>AuthenticationMethod</key>
<string>Password</string>
<key>ProviderType</key>
<string>packet-tunnel</string>
<key>OnDemandUserOverrideDisabled</key>
<integer>1</integer>
<key>RemoteAddress</key>
<string>172.17.28.1:51820</string>
<key>OnDemandEnabled</key>
<integer>1</integer>
<key>OnDemandRules</key>
<array>
<dict>
<key>Action</key>
<string>Connect</string>
</dict>
</array>
<key>ProviderBundleIdentifier</key>
<string>some.bundle.id.network-extension</string>
</dict>
<key>VPNSubType</key>
<string>some.bundle.id</string>
<key>VPNType</key>
<string>VPN</string>
<key>VPNUUID</key>
<string>d2773557-b535-414f-968a-5447d9c02d52</string>
<key>OnDemandMatchAppEnabled</key>
<true />
<key>VendorConfig</key>
<dict>
<key>VPNConfig</key>
<string>
Some custom configuration here
</string>
</dict>
<key>UserDefinedName</key>
<string>TestVPNServerrra</string>
<key>PayloadType</key>
<string>com.apple.vpn.managed.applayer</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadIdentifier</key>
<string>vpn.5e6b56be-a4bb-41a5-949e-4e8195a83f0f</string>
<key>PayloadUUID</key>
<string>9bebe6e2-dbef-4849-a1fb-3cca37221116</string>
<key>PayloadDisplayName</key>
<string>Vpn</string>
<key>PayloadDescription</key>
<string>Configures VPN settings</string>
<key>PayloadOrganization</key>
<string>someorganization</string>
</dict>
</array>
</dict>
</plist>
Command to set up per-app with Chrome browser
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Inc//DTD PLIST 1.0//EN" http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
<key>Command</key>
<dict>
<key>Settings</key>
<array>
<dict>
<key>Identifier</key>
<string>com.google.chrome.ios</string>
<key>Attributes</key>
<dict>
<key>VPNUUID</key>
<string>d2773557-b535-414f-968a-5447d9c02d52</string>
<key>TapToPayScreenLock</key>
<false />
<key>Removable</key>
<true />
</dict>
<key>Item</key>
<string>ApplicationAttributes</string>
</dict>
</array>
<key>RequestType</key>
<string>Settings</string>
</dict>
<key>CommandUUID</key>
<string>17ce3e19-35ef-4dbc-83d9-4ca2735ac430</string>
</dict>
</plist>
From the log we see that our VPN application set up allowed IP 1.1.1.1 via NEIPv4Settings.includedRoutes but system routing all of the Chrome browser traffic through our application.
Is this expected Apple iOS behavior, or are we misconfiguring the profiles?
We have an iOS companion app that talks to our IoT device over the device’s own Wi‑Fi network (often with no internet). The app performs bi-directional, safety-critical duties over that link.
We use an NEAppPushProvider extension so the handset can keep exchanging data while the UI is backgrounded. During testing we noticed that if the user backgrounds the app (still connected to the device’s Wi‑Fi) and opens Safari, the extension’s stop is invoked with NEProviderStopReason.unrecoverableNetworkChange / noNetworkAvailable, and iOS tears the extension down. Until the system restarts the extension (e.g. the user foregrounds our app again), the app cannot send/receive its safety-critical data.
Questions:
Is there a supported way to stop a safety-critical NEAppPushProvider from being terminated in this “background app → open Safari” scenario when the device remains on the same Wi‑Fi network (possibly without internet)?
If not, is NEAppPushProvider the correct extension type for an always-on local-network use case like this, or is there another API we should be using?
For safety-critical applications, can Apple grant entitlements/exemptions so the system does not terminate the extension when the user switches apps but stays on the local Wi‑Fi?
Any guidance on the expected lifecycle or alternative patterns for safety-critical local connectivity would be greatly appreciated.
I am seeking assistance with how to properly handle / save / reuse NWConnections when it comes to the NWBrowser vs NWListener.
Let me give some context surrounding why I am trying to do what I am.
I am building an iOS app that has peer to peer functionality. The design is for a user (for our example the user is Bob) to have N number of devices that have my app installed on it. All these devices are near each other or on the same wifi network. As such I want all the devices to be able to discover each other and automatically connect to each other. For example if Bob had three devices (A, B, C) then A discovers B and C and has a connection to each, B discovers B and C and has a connection to each and finally C discovers A and B and has a connection to each.
In the app there is a concept of a leader and a follower. A leader device issues commands to the follower devices. A follower device just waits for commands. For our example device A is the leader and devices B and C are followers. Any follower device can opt to become a leader. So if Bob taps the “become leader” button on device B - device B sends out a message to all the devices it’s connected to telling them it is becoming the new leader. Device B doesn’t need to do anything but device A needs to set itself as a follower. This detail is to show my need to have everyone connected to everyone.
Please note that I am using .includePeerToPeer = true in my NWParameters. I am using http/3 and QUIC. I am using P12 identity for TLS1.3. I am successfully able to verify certs in sec_protocal_options_set_verify_block. I am able to establish connections - both from the NWBrowser and from NWListener. My issue is that it’s flaky. I found that I have to put a 3 second delay prior to establishing a connection to a peer found by the NWBrowser. I also opted to not save the incoming connection from NWListener. I only save the connection I created from the peer I found in NWBrowser. For this example there is Device X and Device Y. Device X discovers device Y and connects to it and saves the connection. Device Y discovers device X and connects to it and saves the connection. When things work they work great - I am able to send messages back and forth. Device X uses the saved connection to send a message to device Y and device Y uses the saved connection to send a message to device X.
Now here come the questions.
Do I save the connection I create from the peer I discovered from the NWBrowser?
Do I save the connection I get from my NWListener via newConnectionHandler?
And when I save a connection (be it from NWBrowser or NWListener) am I able to reuse it to send data over (ie “i am the new leader command”)?
When my NWBrowser discovers a peer, should I be able to build a connection and connect to it immediately?
I know if I save the connection I create from the peer I discover I am able to send messages with it. I know if I save the connection from NWListener - I am NOT able to send messages with it — but should I be able to?
I have a deterministic algorithm for who makes a connection to who. Each device has an ID - it is a UUID I generate when the app loads - I store it in UserDefaults and the next time I try and fetch it so I’m not generating new UUIDs all the time. I set this deviceID as the name of the NWListener.Service I create. As a result the peer a NWBrowser discovers has the deviceID set as its name. Due to this the NWBrowser is able to determine if it should try and connect to the peer or if it should not because the discovered peer is going to try and connect to it.
So the algorithm above would be great if I could save and use the connection from NWListener to send messages over.