Search code examples
swiftswiftuibluetoothiobluetooth

Scan Nearby Bluetooth Devices Swift 5 - macOS


All,

I am looking to write some code to work with bluetooth. Initially I want to scan and get a list of nearby devices. I would then filter that by device type to only allow a user to connect certain types of devices. Since these devices are headsets, mice, keyboards etc I think they are not LE Bluetooth devices so I dont think I can use CoreBluetooth. I have searched around here and in Apple's developer docs. I have the following code to create an IOBluetoothDeviceInquiryDelegate, then create the object using the delegate and start a search.

The issue is that once I start the search nothing happens. I dont get started or device found even when I know there are devices to find. Here is the starter code I am working with. Note that I have enabled Bluetooth, and am able to list paired devices without issue with some other code. Just cannot search.

import IOBluetooth
import SwiftUI

class BluetoothSearchDelegate : NSObject, IOBluetoothDeviceInquiryDelegate {
    func deviceInquiryDeviceFound(_ sender: IOBluetoothDeviceInquiry, device: IOBluetoothDevice) {
        print("Found Device \(device.name ?? "nil")")
    }
    
    func deviceInquiryStarted(_ sender: IOBluetoothDeviceInquiry) {
        print("started")
    }
    
    func deviceInquiryComplete(_ sender: IOBluetoothDeviceInquiry, error: IOReturn, aborted: Bool) {
        print("completed")
    }
}

struct ContentView: View {
    
    var body: some View {
        Button(action: {
            let delegate = BluetoothSearchDelegate()
            let inquiry = IOBluetoothDeviceInquiry(delegate: delegate)
            inquiry!.start()
            
        }, label: {
            Text("Bluetooth")
                .padding()
        })
    }
}

Solution

  • The following example code worked for me. Using these target settings:

    Signing & Capabilities -> App Sandbox -> Hardware -> Bluetooth ticked

    Info -> Privacy - Bluetooth Always Usage Description -> some message

    struct ContentView: View {
        let delegate = BluetoothSearchDelegate()
        let inquiry: IOBluetoothDeviceInquiry
        
        init() {
            self.inquiry = IOBluetoothDeviceInquiry(delegate: delegate)
        }
        
        var body: some View {
            Button("Bluetooth") {
                inquiry.start()
            }
        }
    }