I am adopting Swift Concurrency in my network extension app to use Swift 6 protections.
In the UI app I ended up with most of the app marked as MainActor, so that pieces of my app can keep seamless access to each other and at the same time have thread safe access.
When it comes to my network extension, does it make sense to also mark most of the code as MainActor for the purposes of thread safety and seamless access of most classes to each other? I have doubts, because MainActor sounds like it should be a UI think, but network extension has no UI
Of course any long or blocking operations would not be MainActor
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 need to know the https address of a certain page within my app. This is going to be used as a redirect URL. I don't think it is a good idea to use deep links because it has to be an https address. I don't think Universal Links will work because it is not my website that I will be communicating with.
Is it possible to capture or inspect UDP traffic using iOS content filter APIs (e.g., NEFilterDataProvider)? If not, what are the current technical or policy limitations that prevent UDP inspection via these frameworks?
Any insights or suggestions on these topics would be highly appreciated.
Is it possible to capture or inspect UDP traffic using iOS content filter APIs (e.g., NEFilterDataProvider)? If not, what are the current technical or policy limitations that prevent UDP inspection via these frameworks?
Any insights or suggestions on these topics would be highly appreciated.
I'm working on enabling a content filter in my iOS app using NEFilterManager and NEFilterProviderConfiguration. The setup works perfectly in debug builds when running via Xcode, but fails on TestFlight builds with the following error:
**Failed to save filter settings: permission denied
**
**Here is my current implementation:
**
(void)startContentFilter {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults synchronize];
[[NEFilterManager sharedManager] loadFromPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Failed to load filter: %@", error.localizedDescription);
[self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to load content filter: %@", error.localizedDescription]];
return;
}
NEFilterProviderConfiguration *filterConfig = [[NEFilterProviderConfiguration alloc] init];
filterConfig.filterSockets = YES;
filterConfig.filterBrowsers = YES;
NEFilterManager *manager = [NEFilterManager sharedManager];
manager.providerConfiguration = filterConfig;
manager.enabled = YES;
[manager saveToPreferencesWithCompletionHandler:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Failed to save filter settings: %@", error.localizedDescription);
[self showAlertWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to save filter settings: %@", error.localizedDescription]];
} else {
NSLog(@"Content filter enabled successfully!");
[self showAlertWithTitle:@"Success" message:@"Content filter enabled successfully!"];
}
});
}];
});
}];
}
**What I've tried:
**
Ensured the com.apple.developer.networking.networkextension entitlement is set in both the app and system extension.
The Network extension target includes content-filter-provider.
Tested only on physical devices.
App works in development build, but not from TestFlight.
**My questions: **
Why does saveToPreferencesWithCompletionHandler fail with “permission denied” on TestFlight?
Are there special entitlements required for using NEFilterManager in production/TestFlight builds?
Is MDM (Mobile Device Management) required to deploy apps using content filters?
Has anyone successfully implemented NEFilterProviderConfiguration in production, and if so, how?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Swift
Network Extension
Objective-C
I am seeking clarification regarding the capabilities and limitations of deploying content filter profiles, such as web content filters, on unsupervised iOS devices through MDM solutions. Specifically, is per-app content filtering supported on unsupervised devices, or is it restricted to supervised devices only? If such restrictions exist, are there recognized workarounds?
Additionally, I would like to understand if there are specific permissions or entitlements that enable apps to perform advanced filtering or monitoring functions on unsupervised devices. Any guidance or references to official documentation would be greatly appreciated.
Hi there, I'm having an issue hoping someone could help. We have an iOS app that uses CoreBluetooth to connect to peripherals using the central manager. The app works great - However, when using the same exact central manager for our watchos app, it will attempt to connect, but I never get a callback for either didConnect or didFailToConnect.
The watch can connect successfully to other BLE devices, so the watch itself is capable of BLE connectivity.
Here's a list of thing's I've tried (unsuccessfully):
1) Added every bluetooth-related entitlement to info.plist
Privacy - Bluetooth Always Usage Description
Privacy - Bluetooth Peripheral Usage Description
Background Modes: App communicates using CoreBluetooth, App shares data using CoreBluetooth
2) Checked for Single-Connection Limits
Verified that the iPhone was fully disconnected from the peripheral to ensure the device wasn’t limited to one connection.
Attempted to connect on watchOS alone (with iPhone turned off)
3) Tried various options for CBCentralManager, scanForPeripherals, and connect
I went through all the keys for various options and tried just setting them, they had no effect
CBCentralManagerOptionShowPowerAlertKey, CBConnectPeripheralOptionEnableTransportBridgingKey
Item 2
4) Tried .registerForConnectionEvents()
5) Set peripheral's delegate to the central in the didDiscover, stored it in a variable to ensure a strong reference to it
I get no warnings either. The last time I ran into something like this, I found out the watchOS blocks TCP sockets. If I print out the CBPeripheralState a few seconds after trying to connect, it shows its stuck on CBPeripheralStateConnecting.
Any advice or direction is greatly appreciated
Below is the code and various print outs (day 2 into debugging, so it's not pretty)
class WatchBLEManager:NSObject,CBCentralManagerDelegate, ObservableObject{
var centralManager: CBCentralManager?
@Published var devices : [String:AtomBLEDevice] = [:]
private var scanningDevice:AtomBLEDevice?
var bleStatus:WatchBLEStatus = .blePoweredOff
func startBLE() {
centralManager = CBCentralManager(delegate: self, queue: nil,options: [CBCentralManagerOptionShowPowerAlertKey: true])
self.centralManager?.delegate = self
}
func startScan() {
self.centralManager?.scanForPeripherals(withServices: [],options: [CBCentralManagerScanOptionAllowDuplicatesKey : true])
self.centralManager?.delegate = self
}
func stopScan() {
print("stopping scan")
self.centralManager?.stopScan()
filterName = ""
scanningDevice = nil
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch (central.state) {
//... other states omitted
case .poweredOff:
bleStatus = .blePoweredOff
// bleStateDelegate?.didBlePoweredOff()
for device in devices.values{
device.isConnected = false
}
print("BLE is Powered Off")
case .poweredOn:
bleStatus = .blePoweredOn
// bleStateDelegate?.didBlePoweredOn()
startScan()
centralManager?.registerForConnectionEvents()
print("Central supports extended scan and connect: ", CBCentralManager.supports(.extendedScanAndConnect))
print("powered on")
@unknown default:
print("BLE is Unknown")
}
}
private let connectionQueue = DispatchQueue(label: "com.atom.connectionQueue")
var connectingTo: String? = nil
var peripheral: CBPeripheral? = nil
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
guard let localName = advertisementData[CBAdvertisementDataLocalNameKey] as? String else { return}
if localName.contains("Atom") {
print("\nConnecting to \(localName)")
print("\tAdvertising data: \(advertisementData)")
print("\tANCS Authorized: ",peripheral.ancsAuthorized)
print("\tServices", peripheral.services, "\n")
self.peripheral = peripheral
self.peripheral?.delegate = self
// central.registerForConnectionEvents()
// central.delegate = self
peripheral.delegate = self
DispatchQueue.main.async {
// central.connect(peripheral)
self.centralManager?.connect(peripheral, options: [ CBConnectPeripheralOptionEnableTransportBridgingKey: true])
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
print("\tState", String(describing: peripheral.state))
print("Connected Peripherals: \(self.centralManager?.retrieveConnectedPeripherals(withServices: []))")
}
}
}
// Never gets called for watchos
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Connected to peripheral: \(peripheral.identifier)")
if let atomDevice = getAtomBLEDevice(peripheral: peripheral) {
//atomDevice.setPeripheral(perpipheral: <#T##CBPeripheral?#>)
atomDevice.isConnected = true
atomDevice.isConnecting = false
//delegate?.didConnected(atomBLE: atomDevice!)
atomDevice.startDiscoveringService()
//atomDevice?.delegate?.didConnected(atomBLE: atomDevice!)
print("Connected: \(peripheral.name)")
} else {
print("no matching atom device found for didConnect")
print("connected peripheral :",peripheral.identifier.uuidString)
}
}
func centralManager(_ central: CBCentralManager, connectionEventDidOccur event: CBConnectionEvent, for peripheral: CBPeripheral) {
print("Connection event: \(event)")
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: (any Error)?) {
print("Failed to connect: \(error?.localizedDescription)")
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
let atomDevice = getAtomBLEDevice(peripheral: peripheral)
atomDevice?.isConnected = false
print("Peripheral disconnected:\(peripheral.name)")
}
func clearData() {
filterName = ""
for device in devices.values{
disconnect(atomBLEDevice: device)
device.perpipheral?.delegate = nil
}
devices = [:]
scanningDevice = nil
// delegate = nil
centralManager = nil
}
}
extension WatchBLEManager: CBPeripheralDelegate {
}```
Issue summary:
Iphone 16 is not connecting to WiFi7 AP with MLO Suiteb encryption. Furuno AP(EW750) is sending EAPOL M1 message, but Iphone16 is not responding with EAPOL M2 message, Hence Iphone16 is unable to connect to Qualcomm based AP with MLO suiteb encryption.
Issue impact:
All the Iphone16 users cannot connect to WiFi7 AP with MLO suiteb encryption globally. Predominantly, Iphone users tend to connect to more secured wifi networks using WPA3 suiteb encryption, hence many of the iphone users will experience the connectivity issue significantly.
Topology:
AP Hardware: Furuno WiFi7 AP(EW770)
The Furuno WiFi7 AP uses Miami IPQ5332 with waikiki radio QCN9274
AP software: SPF12.2 CSU3
IPhone16 software: (18.3.1 or 18.5 )
Iphone16 wifi capabilities: 802.11 b/a/g/n/ac/ax/be
Radius server details:
Radius server: Laptop running with Ubuntu
Radius package: 3.0.26dfsggit20220223.1.00ed0241fa-0ubuntu3.4
Version: 3.0.26
Steps:
Power on the Wi-Fi 7 Access Point with the Miami chipset, and flash it with the SPF 12.2 CSU3 image.
Enable both 5 GHz and 6 GHz radios on the AP.
Enable MLO (Multi-Link Operation) in 6Ghz & 5Ghz, set MLD address different from radio address and configure Suite-B (192-bit) encryption
On the Linux laptop, set up the RADIUS server with EAP-TLS authentication method.
Once the above steps are completed, take the iPhone 16 and follow the steps below to install the RADIUS client certificates on the device.
On the sniffer laptop, switch the Wi-Fi adapter to monitor mode, configure the required channel, and begin packet capture.
Check SSID is broadcasting, then connect the iPhone 16 to .
Verify if the client (iPhone 16) connects to the SSID using WPA3-Enterprise, MLO, and Suite-B encryption by checking the wireless capture on both the AP and iPhone sides.
Support needed from Apple team:
We would request Apple team to analyse and enable the IPhone16 users to connect to advanced security WPA3 Suiteb by resolving the issue.
Below is our analysis and observation for your reference.
As per IEEE, MLD mac address can be set to the same or different from radio address, Iphone16 is not accepting EAPOL M1 message if source address(MLD) is different from radio address.
IPhone16 is accepting EAPOL M1 if the source address(MLD) is set to the same as the radio address and responds with M2 message
IPhone16 is not accepting EAPOL M1 if source address(MLD) set to different from radio address and fails to respond with M2 message
Hi,
I’m urgently seeking assistance with an issue in my app development.
The app allows users to control which domains are routed through my relay servers (six server URLs).
However, I’ve encountered a problem:
When a single relay configuration (for a single server URL) contains more than 70 domains, only one configuration can be active at a time. If I manually activate another relay configuration (for another server URL), the previously activated one automatically deactivates.
Is there a way to overcome this limitation?
Also, is there a maximum amount of domains that can exist across the per-app relays?
I’m referencing the Apple documentation here:
https://developer.apple.com/documentation/networkextension/relays
Any guidance or insights into resolving this issue would be greatly appreciated!
Thank you in advance :)
Hi everyone, I developed an Android version of a VPN app built with Flutter using OpenVPN, and it works perfectly on Android. However, when porting it to iOS, I’ve encountered an issue: the app connects successfully but then automatically disconnects when tested via TestFlight. We’ve already added all the necessary network extensions. Despite this, we decided to submit the app to the App Store. It’s been five days now, and the app is still 'Waiting for Review.' Could anyone share their experience deploying and working on an iOS version of a VPN app? I’d really appreciate your insights!
How can NEPacketTunnelProvider launch the companion application, or notify user to launch the application?
I have built an iOS VPN that uses credentials stored in the keychain, and it works as expected. Now I'm trying to add OAuth login support.
Everything works fine at first. I login from the companion application, store tokens in the keychain, then launch the VPN from either System Settings or the companion application.
However, when the OAuth refresh tokens expire, or the OAuth IdP otherwise requires login, I can't perform the OAuth login from the NEPacketTunnelProvider. Login must happen from the companion application, which likely isn't running. I need the NEPacketTunnelProvider to either launch the companion application directly or to notify the user to do so.
Searching and reading docs yields:
You can't perform OAuth login from within the NEPacketTunnelProvider because it requires user interaction
There is no way to guarantee that the companion application is running on iOS (otherwise one would use NEVPNStatusDidChange)
You can't launch the companion application from NEPacketTunnelProvider using a custom URL because of security concerns
You might be able to launch the companion application from a system extension...
Some sources say you still can't guarantee that the system extension is loaded whenever the NEPacketTunnelProvider needs it anyway.
Of course, any of these conclusions could be wrong.
At this point I'm not sure where to begin. Is there another approach that could be initiated by the NEPacketTunnelProvider (push notifications, system notifications, smoke signals)?
Any help would be appreciated.
Thanks,
Bill Welch
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Network Extension
User Notifications
As a third-party application on Apple Watch, can it be located in the same LAN httpServer? Currently, when testing to initiate an http request in the LAN, the connection timeout is returned, code: -1001
self.customSession.request("http://10.15.48.191:9000/hello").response { response in
switch response.result {
case .success(let data):
dlog("✅ 请求成功,收到数据:")
if let html = String(data: data ?? Data(), encoding: .utf8) {
dlog(html)
}
case .failure(let error):
dlog("❌ 请求失败:\(error.localizedDescription)")
}
}
执行后报错
Task <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "请求超时。" UserInfo={_kCFStreamErrorCodeKey=-2102, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>",
"LocalDataPDTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>",
"LocalDataTask <B71BE820-FD0E-4880-A6DD-1F8F6EAF98B0>.<1>"
), NSLocalizedDescription=请求超时。, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=http://10.15.48.191:9000/hello, NSErrorFailingURLKey=http://10.15.48.191:9000/hello}
Could anyone tell me how to detect status of Local Network for iOS 18+ systems ?
Hi everyone,
I'm building a health-focused iOS and watchOS app that uses WatchConnectivity to sync real-time heart rate and core body temperature data from iPhone to Apple Watch. While the HealthKit integration works correctly on the iPhone side, I'm facing persistent issues with WatchConnectivity — the data either doesn't arrive on the Watch, or session(_:didReceiveMessage:) never gets triggered.
Here's the setup:
On iPhone: Using WCSession.default.sendMessage(_:replyHandler:errorHandler:) to send real-time values every few seconds.
On Apple Watch: Implemented WCSessionDelegate, and session(_:didReceiveMessage:) is supposed to update the UI.
Both apps have WCSession.isSupported() checks, activate the session, and assign delegates correctly.
The session state shows isPaired = true and isWatchAppInstalled = true.
Bluetooth and Wi-Fi are on, both devices are unlocked and nearby.
Despite all this, the Watch never receives messages in real-time. Sometimes, data comes through in bulk much later or not at all.
I've double-checked Info.plist configurations and made sure background modes include "Uses Bluetooth LE accessories" and "Background fetch" where appropriate.
I would really appreciate guidance on:
Best practices for reliable, low-latency message delivery with WatchConnectivity.
Debugging steps or sample code to validate message transmission and reception.
Any pitfalls related to UI updates from the delegate method.
Happy to share further details. Thanks in advance!
Topic:
App & System Services
SubTopic:
Networking
Tags:
Watch Connectivity
Health and Fitness
watchOS
Apple Watch
hi all.
I’m working on a content filter system extension on MacOS.
I try to disable the filtering in system settings, and it will cause smb shared folder connection interrupted.
what I do in stopFilterWithReason:completionHandler: is waiting for the connection that is being filtered be allowed, then invoked the completionHandler.
did I do something wrong here? is there a way to avoid the connection interruption?
Hi,
I would like to confirm whether the matchDomains property in NERelayManager operates strictly at the Application Layer. Specifically, it seems that adding IPv4 addresses or IPv4 CIDR blocks to the matchDomains list does not work, as the relay manager appears unable to match them.
For example, I tried adding the following IPv4 patterns to the matchDomains list:
11.22.33.44
11.22..
11.22.*
However, these IPv4 addresses or patterns are not routed through my Relay server.
Additionally, I have observed that when using only the excludedDomains property, the desired IPv4 traffic is correctly routed to the relay server as expected.
My question is: Can IPv4 addresses or IPv4 CIDR ranges work with matchDomains? If not, is there an alternative approach to enable IPv4 matching while matchDomains is active?
Topic:
App & System Services
SubTopic:
Networking
Tags:
Extensions
Network Extension
Network
System Configuration
I am developing an iOS application using NWPathMonitor for network connectivity monitoring. We discovered a reproducible issue where disabling and re-enabling WiFi triggers an unexpected network status sequence.
ENVIRONMENT:
iOS Version: 17.x
Device: iPhone (various models tested)
Network Framework: NWPathMonitor from iOS Network framework
STEPS TO REPRODUCE:
Device connected to WiFi normally
Disable WiFi via Settings or Control Center
Re-enable WiFi via Settings or Control Center
EXPECTED BEHAVIOR:
WiFi reconnects and NWPathMonitor reports stable satisfied status
ACTUAL BEHAVIOR:
T+0s: WiFi re-enables, NWPathMonitor reports path.status = .satisfied
T+8s: NWPathMonitor unexpectedly reports path.status = .unsatisfied with unsatisfiedReason = .notAvailable
T+9-10s: NWPathMonitor reports path.status = .satisfied again
Connection becomes stable afterward
NETWORK PATH TIMELINE:
T+0s: satisfied (IPv4: true, DNS: false)
T+140ms: satisfied (IPv4: true, DNS: true)
T+8.0s: unsatisfied (reason: notAvailable, no interfaces available)
T+10.0s: satisfied (IPv4: true, DNS: true)
KEY OBSERVATIONS:
Timing consistency: unsatisfied event always occurs ~8 seconds after reconnection
resolution: "Reset Network Settings" eliminates this behavior
TECHNICAL QUESTIONS:
What causes the 8-second delayed unsatisfied status after WiFi re-enablement?
Is this expected behavior that applications should handle?
Why does reset network setting in iPhone fix this issue?
Dear Team,
I was previously able to access a non-secure HTTP API in my Ionic-built app. However, I am now encountering an error where the API requests are being rejected. Interestingly, this API works perfectly on Android and web platforms without any issues.
As part of my troubleshooting, I have already added the following lines to my Info.plist file:
`<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>`
Could you kindly suggest any alternative solutions or additional settings required to access this HTTP API?
Your help would be greatly appreciated.
Thank you,
Mozib
I am unable to apply for Multicast Entitlement at https://developer.apple.com/contact/request/networking-multicast
The reason for this is unclear. I have paid for a developer account and believe I'm up to date with all agreements.
Topic:
App & System Services
SubTopic:
Networking
Question: Best Practice for NEFilterRule and NENetworkRule Initializers with Deprecated NEHostEndpoint?
Hi all,
I'm looking for guidance on the right way to construct an NEFilterRule that takes a NENetworkRule parameter. Reading the latest documentation, it looks like:
All initializers for NENetworkRule that accept an NEHostEndpoint are now deprecated, including initWithDestinationHost:protocol: and those using the various *Network:prefix: forms. NEHostEndpoint itself is also deprecated; Apple recommends using the nw_endpoint_t type from the Network framework instead.
However, NEFilterRule still requires a NENetworkRule for its initializer (docs).
With all NENetworkRule initializers that take NEHostEndpoint deprecated, it’s unclear what the recommended way is to create a NENetworkRule (and thus an NEFilterRule) that matches host/domain or network traffic.
What’s the proper way to construct these objects now—should we create the endpoints using nw_endpoint_t and use new/undocumented initializers, or is there an updated approach that’s considered best practice?
Helpful doc links for reference:
NEFilterRule docs
NENetworkRule docs
NWHostEndpoint (now deprecated)