Post

Replies

Boosts

Views

Activity

CoreWLAN scanForNetworks does not expose SSIDs even when Location permission is authorized (Sequoia 15.1)
Hi, I've read a bunch of threads regarding the changes in Sonoma and later requiring Location permission for receiving SSIDs. However, as far as I can see, in Sequoia 15.1 SSIDs and BSSIDs are empty regardless. In particular, this makes it not possible to use associate(withName:) and associate(withSSID:) because the network object returned by scanForNetwork(withSSID: "...") has its .ssid and .bssid set to nil. Here is an example: First we have a wrapper to call the code after the location permission is authorized: import Foundation import CoreLocation class LocationDelegate: NSObject, CLLocationManagerDelegate { var onAuthorized: (() -> Void)? var onDenied: (() -> Void)? func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { let authStatus = manager.authorizationStatus print("Location authorization status changed: \(authStatusToString(authStatus))") if authStatus == .authorizedAlways { onAuthorized?() } else if authStatus == .denied || authStatus == .restricted { onDenied?() } } } let locationManager = CLLocationManager() let locationDelegate = LocationDelegate() func authorizeLocation(onAuthorized: @escaping () -> Void, onDenied: @escaping () -> Void) { let authStatus = locationManager.authorizationStatus print("Location authorization status: \(authStatusToString(authStatus))") if authStatus == .notDetermined { print("Waiting for location authorization...") locationDelegate.onAuthorized = onAuthorized locationDelegate.onDenied = onDenied locationManager.delegate = locationDelegate locationManager.requestAlwaysAuthorization() } else if authStatus == .authorizedAlways { onAuthorized() } else if authStatus == .denied || authStatus == .restricted { onDenied() } RunLoop.main.run() } func authStatusToString(_ status: CLAuthorizationStatus) -> String { switch status { case .notDetermined: return "Not Determined" case .restricted: return "Restricted" case .denied: return "Denied" case .authorizedAlways: return "Always Authorized" case .authorizedWhenInUse: return "Authorized When In Use" @unknown default: return "Unknown" } } Then, a demo program itself: import Foundation import CoreWLAN import Network let client = CWWiFiClient.shared() guard let interface = client.interface() else { print("No wifi interface") exit(1) } authorizeLocation( onAuthorized: { do { print("Scanning for wifi networks...") let scanResults = try interface.scanForNetworks(withSSID: nil) let networks = scanResults.compactMap { network -> [String: Any]? in return [ "ssid": network.ssid ?? "unknown", "bssid": network.bssid ?? "unknown" ] } let jsonData = try JSONSerialization.data(withJSONObject: networks, options: .prettyPrinted) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) } exit(0) } catch { print("Error: \(error)") exit(1) } }, onDenied: { print("Location access denied") exit(1) } ) When launched, the program asks for permission, and after that, is shown as enabled in Privacy & Security Settings panel. Here is the output where it can be seen that the scan is performed after location access was authorized, and regardless of that, all ssids are empty: Location authorization status: Not Determined Waiting for location authorization... Location authorization status changed: Always Authorized Scanning for wifi networks... [ { "ssid" : "unknown", "bssid" : "unknown" }, { "ssid" : "unknown", "bssid" : "unknown" }, .... further omitted Calling scanForNetworks() with explicitly specified network name does this as well, returns a CWNetwork object with .ssid / .bssid = nil.
5
0
318
Nov ’24