Cannot scan for iBeacons (macOS)

Hello,

I am attempting a very simple AppKit app on MacOS which displays nearby iBeacons.

I don't appear to ever have region scanning available on my system though. Am I doing something wrong?

FYI: My system is a MacBook Pro (16-inch, 2019) running Catalina (10.15.7)

The target has 'Bluetooth' and 'App Location' enabled in the 'App Sandbox' capabilities section and 'Location' enabled under 'Hardened Runtime'.


For a second question: is it possible to scan for any beacons, not just my own (i.e. scan without setting a proximity UUID)?

//  ViewController.swift
//  Beacons

import Cocoa
import CoreLocation

class ViewController: NSViewController, CLLocationManagerDelegate {

    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager = CLLocationManager()
        locationManager.requestAlwaysAuthorization()
        locationManager.delegate = self
    }

    @IBAction func buttonTapped(_ sender: NSButton) {
        self.startScanning()
    }

    override var representedObject: Any? {
        didSet {
            // Update the view, if already loaded.
        }
    }

    func startScanning() {
        print("starting scanning")

    //UUID Obscured for forum post...
        guard let uuid = UUID(uuidString: "xxxxxxxx-E4A1-4720-9034-xxxxxxxxxxxx") else {
            print("Couldn't make UUID")
            return
        }

        let beaconID = "com.monkeyfood.myBeaconRegion"
        let beaconRegion = CLBeaconRegion(uuid: uuid, identifier: beaconID)

//        let beaconRegion = CLBeaconRegion(uuid: UUID(), identifier: beaconID)

        self.locationManager.startMonitoring(for: beaconRegion)
    }

    
    //.   CLLocationManagerDelegate Methods
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        var newStatus = ""
        switch status {
        case .notDetermined:
            newStatus = "Not determined"
        case .restricted:
            newStatus = "Restricted"
        case .denied:
            newStatus = "Denied"
        case .authorizedAlways:
            newStatus = "Authorised Always"
        case .authorized:
            newStatus = "Authorised"
        default:
            newStatus = "What?"
        }
        print("LM Auth Status is now: \(newStatus)")

//  Check for iBeacon monitoring status
        let regionMonitoringIsAvailable = CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self)
        let not = regionMonitoringIsAvailable ? "" : "not "
        print("Beacon monitoring is \(not)available")
    }


    func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
        if beacons.count > 0 {
//            updateDistance(beacons[0].proximity)
            print("\(beacons.count) beacons found.")
            print("\(beacons[0].proximity) dist.")
        } else {
//            updateDistance(.unknown)
        }
    }

    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        print("region entered... \(region)")
    }

    func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
        print("region exited... \(region)")
    }

    func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
        print("determined  region state")
    }

    func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
        print("region monitoring failed: \(error)")
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("LM failed \(error)")
    }

}

Always gives me the following:

LM Auth Status is now: Authorised Always
Beacon monitoring is not available
starting scanning
region monitoring failed: Error Domain=kCLErrorDomain Code=5 "(null)"

Replies

I cross-posted to StackOverflow and got this useful answer:

https://stackoverflow.com/a/68397848/568104

Apparently iBeacon APIs are not available on MacOS, despite the docs stating that they are available on MacOS.