Search code examples
swiftxcodeswiftuicore-bluetooth

Swiftui - Bluetooth Low Energy status is always unknown


I have a program on swiftui using BLE. But when I want to know the status of the centralManager (my iPhone) , it displays unknown. I don't know if there is an error in my code or the problem is with my phone.

My Contentview :

import SwiftUI
import CoreBluetooth

struct ContentView: View {
    var body: some View {
        VStack {
            Text("View").background(Color.init(red: 56, green: 22, blue: 22))
        }
        .onAppear(perform: connectBLEDevice)
    }
    private func connectBLEDevice(){
        print("connectBLEDevice")
        let ble = BLEConnection()
        ble.startCentralManager()
    }
}

My class for BLE :

import CoreBluetooth

class BLEConnection: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    var centralManager: CBCentralManager!
    var myPeripheral: CBPeripheral!

func startCentralManager() {
    self.centralManager = CBCentralManager(delegate: self, queue: nil)
    print("Central Manager State: \(self.centralManager.state)")
    centralManagerDidUpdateState(self.centralManager)
}

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    switch (central.state) {
       case .unsupported:
        print("BLE is Unsupported")
        break
       case .unauthorized:
        print("BLE is Unauthorized")
        break
       case .unknown:
        print("BLE is Unknown")
        break
       case .resetting:
        print("BLE is Resetting")
        break
       case .poweredOff:
        print("BLE is Powered Off")
        break
       case .poweredOn:
        print("BLE powered on")
        break
    @unknown default:
        break
    }
}
}

Solution

  • Here are some fixes

    struct ContentView: View {
        private let ble = BLEConnection() // make member !!
    
        var body: some View {
            VStack {
                Text("View").background(Color.init(red: 56, green: 22, blue: 22))
            }
            .onAppear(perform: connectBLEDevice)
        }
    
        private func connectBLEDevice(){
            print("connectBLEDevice")
            ble.startCentralManager()
        }
    }
    

    Delegate will be called by BLE engine asynchronously, so don't force call it - just add handling code for each state

    func startCentralManager() {
        self.centralManager = CBCentralManager(delegate: self, queue: nil)
    
    //    print("Central Manager State: \(self.centralManager.state)") //
    //    centralManagerDidUpdateState(self.centralManager)  // << wrong !!
    }