附近使用 Swift 3.0 的蓝牙设备

Nearby Bluetooth devices using Swift 3.0

我正在寻找一种方法来以编程方式列出我的设备找到的任何附近的蓝牙设备(可发现的)。我无法找到有关在 Swift 3.0 中执行此调用的任何信息或教程。 Q-A post 讨论了使用 Swift 1.0 并在 Xcode 6 而不是最新版本 8 中构建这些设备。

我尽最大努力使我的代码从 1.0 变成 3.0 语法,但是 运行 以下代码在 Playground 中没有返回任何内容:

import Cocoa
import IOBluetooth
import PlaygroundSupport

class BlueDelegate : IOBluetoothDeviceInquiryDelegate {
    func deviceInquiryComplete(_ sender: IOBluetoothDeviceInquiry, error: IOReturn, aborted: Bool) {
        aborted
        print("called")
        let devices = sender.foundDevices()
        for device : Any? in devices! {
            if let thingy = device as? IOBluetoothDevice {
                thingy.getAddress()
            }
        }
    }
}

var delegate = BlueDelegate()
var inquiry = IOBluetoothDeviceInquiry(delegate: delegate)
inquiry?.start()
PlaygroundPage.current.needsIndefiniteExecution = true

正确使用 IOBluetooth

以下代码在 Xcode 版本 8.2.1 (8C1002)、Swift 3.0 中完美运行。有几行不是必需的,例如 deviceInquiryStarted.

的整个方法

更新:从 Xcode 9.2 (9B55) 和 Swift 4.

开始,这些用法仍然有效

游乐场

import Cocoa
import IOBluetooth
import PlaygroundSupport
class BlueDelegate : IOBluetoothDeviceInquiryDelegate {
    func deviceInquiryStarted(_ sender: IOBluetoothDeviceInquiry) {
        print("Inquiry Started...")
//optional, but can notify you when the inquiry has started.
    }
    func deviceInquiryDeviceFound(_ sender: IOBluetoothDeviceInquiry, device: IOBluetoothDevice) {
        print("\(device.addressString!)")
    }
    func deviceInquiryComplete(_ sender: IOBluetoothDeviceInquiry!, error: IOReturn, aborted: Bool) {
//optional, but can notify you once the inquiry is completed.
    }
}
var delegate = BlueDelegate()
var ibdi = IOBluetoothDeviceInquiry(delegate: delegate)
ibdi?.updateNewDeviceNames = true
ibdi?.start()
PlaygroundPage.current.needsIndefiniteExecution = true

Project-Application 用法

import Cocoa
import IOBluetooth
import ...
class BlueDelegate : IOBluetoothDeviceInquiryDelegate {
    func deviceInquiryStarted(_ sender: IOBluetoothDeviceInquiry) {
        print("Inquiry Started...")
}
    func deviceInquiryDeviceFound(_ sender: IOBluetoothDeviceInquiry, device: IOBluetoothDevice) {
        print("\(device.addressString!)")
    }
}

//other classes here:



//reference the following outside of any class:
var delegate = BlueDelegate()
var ibdi = IOBluetoothDeviceInquiry(delegate: delegate)

//refer to these specifically inside of any class:
ibdi?.updateNewDeviceNames = true
ibdi?.start() //recommended under after an action-button press.

说明

我最初面临的问题是试图访问信息,因为查询仍在进行中。

当我访问它时,在许多不同的情况下,我的游乐场会挂起,我会被迫从 Activity 监视器中强制退出 Xcode.app 和 com.apple.CoreSimulator.CoreSimulatorService。我让自己相信这只是一个 Playground 错误,结果发现一旦查询完成我的应用程序就会崩溃。

正如 Apple 的 API Reference 所述:

Important Note: DO NOT perform remote name requests on devices from delegate methods or while this object is in use. If you wish to do your own remote name requests on devices, do them after you have stopped this object. If you do not heed this warning, you could potentially deadlock your process.

这完全解释了我的问题。我没有直接从 sender.foundDevices() 方法中请求 IOBluetoothDevice 信息(我相信它可能没有更新..?)我只是使用函数内置的参数来说明它确实是一个 IOBluetoothDevice 对象,并简单地要求打印该信息。

最后的笔记

我希望我创建的这个 Q/A 在 Swift 中使用 IOBluetooth 时能帮助有需要的其他人。缺少任何教程和大量过时的 Objective-C 代码使得查找此信息非常困难。我要感谢@RobNapier 在开始尝试找到这个 谜语 的答案时给予的支持。我还要感谢 NotMyName 在 Apple 开发者论坛上对我 post 的回复。

我迟早会探索在 iOS 设备中使用它!