如何通过 Swift 以编程方式重置蓝牙

How to Programmatically Reset Bluetooth via Swift

我在 Swift 4 中有一个应用程序可以通过蓝牙 LE 与其他应用程序进行通信。它通过了所有测试并在 "fresh" iPhone 上工作。 "fresh" 我的意思是它在最后一天被重置并且没有 太多 与其他经典蓝牙设备的其他交互。我说 太多 因为我无法真正量化它。一些 iPhones 在连接到经典蓝牙设备(汽车、耳机等)后会立即工作,而其他人则不会。有些甚至根本没有表现出这种行为。修复很简单:只需重新启动 iPhone。这似乎发生在 iPhone SE 及以后(无法更早测试)。然而,它永远不会发生在 iPad 上。

我的问题是:有没有办法以编程方式重置 iOS 中的蓝牙无线电或 BLE 堆栈? 我似乎无法解决这个问题。日志或调试器中没有显示任何内容。当发生这种情况时,设备只是 等待 蓝牙连接,而坐在它旁边的 "fresh" 设备将建立连接。我试图将我的 peripheralManager 设置为 nil 来重置它,但没有成功。我还尝试将 UUID 临时设置为其他内容,同样没有成功。

有什么想法吗?

// BLE Constructor
override init() {

    // Super
    super.init()

    // Initialize Location Manager
    globalLocationManager.delegate = self
    globalLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
    globalLocationManager.requestAlwaysAuthorization()

    // Start Updating Location
    globalLocationManager.startUpdatingLocation()

    // Log
    AppDelegate.log( "Initializing Bluetooth LE Peripheral Manager" )

    // Initialize Peripheral Manager
    let options: Dictionary<String, AnyObject> = [ CBPeripheralManagerOptionShowPowerAlertKey: true as AnyObject ]
    peripheralManager = CBPeripheralManager( delegate: self, queue: nil, options: options )            // nil Queue == Main Queue

    // Initialize Packet Counters
    counter = 0
}

// Start Advertising
func startAdvertising() {

    // Evaluate Advertising State
    if peripheralManager.isAdvertising == false {

        // Start Advertising
        AppDelegate.log( "Starting Advertisements" )

        // Reset Simulation
        resetSimulation()         

        let advertisementData = [
            CBAdvertisementDataLocalNameKey: "TEST" as AnyObject,
            CBAdvertisementDataServiceUUIDsKey: [cbUUID]
        ] as [String : AnyObject]

        peripheralManager.startAdvertising( advertisementData )
    }
}

遗憾的是,无法以编程方式重新启动蓝牙。 iPhone 非常重视缓存蓝牙数据以保护电池,因此如果 BLE 设备提供的服务或特性发生变化,phone 将不会接收它们,除非您重新启动蓝牙甚至 phone 手动的。希望苹果以后给开发者更多的控制权。