从不调用centralManager didConnectPeripheral

时间:2016-07-04 21:39:42

标签: swift macos core-bluetooth bluetooth-lowenergy

我一直在研究一段代码来连接表中的BLE设备。我能够发现设备并将它们加载到表中。在表格中的行选择上,我请求连接所选设备。但是,didConnectPeripheral永远不会被调用...

任何想法:

import UIKit
import CoreBluetooth

@objc protocol BLEDelegate: class {

    func srgDiscoverServices(sender: BLEDiscovery, peripheral: CBPeripheral)

}

let bleDiscoverySharedInstance = BLEDiscovery()

//MARK: - UUIDS for StingRay Genessis M (SRG)
let StingRayGenesisMUUID    = CBUUID    (string: "346D0000-12A9-11CF-1279-81F2B7A91332") //Core UUID

//MARK: - Device and Characteristic Registers
var BLEDevices          : [CBPeripheral] = []           //Device Array
var BLECharDictionary   = [String: CBCharacteristic]()  //Characteristic Dictionary


class BLEDiscovery: NSObject, CBCentralManagerDelegate {

    private var centralManager : CBCentralManager?

    weak var delegate: BLEDelegate?

    override init() {
        super.init()

        let centralQueue = dispatch_queue_create("com.stingray", DISPATCH_QUEUE_SERIAL)
        centralManager = CBCentralManager(delegate: self, queue: centralQueue)

    }

    // MARK: - CBCentralManager
    func centralManagerDidUpdateState(central: CBCentralManager) {
        switch (central.state) {

            case CBCentralManagerState.PoweredOff:
                print("CBCentralManagerState.PoweredOff")

            case CBCentralManagerState.Unauthorized:
                // Indicate to user that the iOS device does not support BLE.
                print("CBCentralManagerState.Unauthorized")
                break

            case CBCentralManagerState.Unknown:
                // Wait for another event
                print("CBCentralManagerState.Unknown")
                break

            case CBCentralManagerState.PoweredOn:
                print("CBCentralManagerState.PoweredOn")
                self.startScanning()

            case CBCentralManagerState.Resetting:
                print("CBCentralManagerState.Resetting")

            case CBCentralManagerState.Unsupported:
                print("CBCentralManagerState.Unsupported")
                break
        }
    }

    // MARK: - Start scanning for StringRay devices with the appropriate UUID
    func startScanning() {
        if let central = centralManager {
            central.scanForPeripheralsWithServices([StingRayGenesisMUUID], options: nil)
        }
    }

    // MARK: - CB Central Manager - Did discover peripheral (follows : startScanning)
    func  centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) {

        print("BLEDiscovery :: didDiscoverPeripheral :: ", peripheral.name)

        //Check if new discovery and append to BLEDevices where required
        if BLEDevices.contains(peripheral) {

        }
        else{
            BLEDevices.append(peripheral)
        }

        //Change to BLEDevices - therefore update MianViewController, but check that the view is loaded
        if MainViewController().deviceTableView != nil {

            print("BLEDiscovery :: deviceTableView :: ")
            MainViewController().relaodDeviceTable()
        }


    }

    // MARK:  - CB Central Manager - Connect and Disconnet BLE Devices

    func connectBLEDevice (peripheral: CBPeripheral){

        print("BLEDiscovery :: connectBLEDevice :: ", peripheral.name)

        //Connect
        let peripheralConnect : CBPeripheral = peripheral
        self.centralManager!.connectPeripheral(peripheralConnect, options: nil)
    }

    func disconnectBLEDevice (peripheral: CBPeripheral){

        print("BLEDiscovery :: disconnectBLEDevice :: ", peripheral.name)

        //Disconnect
        let peripheralDisconnect : CBPeripheral = peripheral
        self.centralManager?.cancelPeripheralConnection(peripheralDisconnect)
    }

    // MARK:  - CB Central Manager - Did Connect Device

    func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {

        print("BLEDiscovery :: didConnectPeripheral :: ", peripheral.name)

        delegate?.srgDiscoverServices(self, peripheral: peripheral)

    }

    func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {

        //error handling
        if (error != nil) {
            print("!!Error - BLE Discovery - didDisconnectPeripheral - Error :: \(error)")
            return
        }

        //On disconnect remove device from register
        if let index = BLEDevices.indexOf(peripheral) {
            BLEDevices.removeAtIndex(index)
        }

        //Change to BLEDevices - therefore update MianViewController
        MainViewController().relaodDeviceTable()

    }

    func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) {

        //error handling
        if (error != nil) {
            print("!!Error - BLE Discovery - didFailToConnectPeripheral - Error :: \(error)")
            return
        }

        //Change to BLEDevices - therefore update MianViewController
        MainViewController().relaodDeviceTable()

    }


}

我知道代码是从表中调用的,因为我可以在日志窗口中观察“BLEDiscovery :: connectBLEDevice ::”,peripheral.name“。

这是我呼叫连接和断开连接的地方:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        print("MainViewController :: didSelectRowAtIndexPath :: Row :: ", deviceTableView.indexPathForSelectedRow?.row)

        let peripheral : CBPeripheral = BLEDevices[(deviceTableView.indexPathForSelectedRow?.row)!]

        switch peripheral.state{

        case .Connected:
            //Disconnect as device is connected
            BLEDiscovery().disconnectBLEDevice(peripheral)
        case .Disconnected:
            //Connect as device as disconnected
            BLEDiscovery().connectBLEDevice(peripheral)

        default: break

        }

    }

1 个答案:

答案 0 :(得分:3)

BLEDiscovery之类的对象最好以单例形式实现,或者您可以使用Dependency Injection,但最重要的是拥有该类的单个实例。

你正在使用全局变量来实现这一点,但是你在didSelectRowAtIndexPath函数中滑落了。当你说

case .Connected:
    //Disconnect as device is connected
    BLEDiscovery().disconnectBLEDevice(peripheral)

您创建了一个新的本地BLEDiscovery实例,其中包含自己的CBCentralManager,这是您要求执行连接的核心。退出case语句后,将释放此本地BLEDiscovery,因此永远不会调用委托方法。如果你将外围设备数组封装在BLEDiscovery类中而不是使用全局数组,那么你可能已经发现了这个错误,因为你必须在访问数组之前得到BLEDiscovery引用,而你会有抛出数组边界异常,因为数组本身是空的。

您可以将BLEDiscovery重构为单身,并消除全局:

class BLEDiscovery: NSObject, CBCentralManagerDelegate {

    static let sharedInstance = BLEDiscovery()
    private static var initialised = false

    private var centralManager : CBCentralManager!

    weak var delegate: BLEDelegate?

    //MARK: - UUIDS for StingRay Genesis M (SRG)
    let stingRayGenesisMUUID    = CBUUID    (string: "346D0000-12A9-11CF-1279-81F2B7A91332") //Core UUID

   //MARK: - Device and Characteristic Registers
   var bleDevices          : [CBPeripheral] = []           //Device Array
   var bleCharDictionary   = [String: CBCharacteristic]()  //Characteristic Dictionary

   override init() {
       assert(!BLEDiscovery.initialised, "Illegal call to initializer - use sharedInstance")

       BLEDiscovery.initialised = true

       super.init()

       let centralQueue = dispatch_queue_create("com.stingray", DISPATCH_QUEUE_SERIAL)
       centralManager = CBCentralManager(delegate: self, queue: centralQueue)
}

// Rest of methods largely unchanged, although you should use `self.bleDevices` etc

现在,当您想要BLEDiscovery的实例时,您可以使用BLEDiscovery.sharedInstance,例如

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    print("MainViewController :: didSelectRowAtIndexPath :: Row :: ", deviceTableView.indexPathForSelectedRow?.row)

    let bleDiscovery = BLEDiscovery.sharedInstance

    let peripheral = bleDiscovery.bleDevices[indexPath.row]

    switch peripheral.state{

    case .Connected:
        //Disconnect as device is connected
        bleDiscovery.disconnectBLEDevice(peripheral)
    case .Disconnected:
        //Connect as device as disconnected
        bleDiscovery.connectBLEDevice(peripheral)

    default: break

    }

}