2016-07-04 13 views
0

Ich habe an einem Stück Code gearbeitet, um BLE-Geräte von einer Tabelle zu verbinden. Ich kann Geräte entdecken und in eine Tabelle laden. Bei der Zeilenauswahl innerhalb der Tabelle fordere ich das ausgewählte Gerät an, verbunden zu werden. Allerdings ist didConnectPeripheral nie genannt ...centralManager didConnectPeripheral wird nie aufgerufen

Irgendwelche Gedanken:

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() 

    } 


} 

ich den Code kennen, aus der Tabelle genannt zu werden, wie ich kann Beobachter "BLEDiscovery :: connectBLEDevice ::" peripheral.name“ . im Log-Fenster

Dies ist, wo ich von An- und Abkuppeln rufen:

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 

     } 

    } 
+0

Dies ist nicht Ihr Problem, aber ist Ihre Hauptansicht Controller ein Singleton? Wenn nicht, wird Ihnen MainViewController() nicht die benötigte Instanz geben. Kannst du zeigen, wo du 'connectBLEDevice' nennst? In 'didSelectRowAtIndexPath'? Ihr 'BLEDiscovery'-Objekt sollte ein Singleton sein und Ihr Peripherie-Array sollte eher eine Eigenschaft dieser Klasse sein als eine globale – Paulw11

Antwort

0

Objekte wie Ihr BLEDiscovery am besten umgesetzt werden als Singleton, oder Sie können Dependency Injection verwenden, aber die Hauptsache ist, eine einzelne Instanz der Klasse zu haben.

Sie verwenden Globals, um dies zu erreichen, aber Sie haben sich in Ihrer didSelectRowAtIndexPath Funktion verirrt. Wenn Sie

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

erstellen Sie eine neue, lokale Instanz von BLEDiscovery, die ihre eigenen CBCentralManager enthält und das ist die zentrale, dass Sie die connect auszuführen fragen. Sobald Sie die case-Anweisung beenden, wird diese lokale BLEDiscovery freigegeben und so die Delegate-Methoden nie aufgerufen werden. Wenn Sie Ihr Peripheriearray innerhalb der BLEDiscovery-Klasse gekapselt und kein globales Array verwendet haben, haben Sie diesen Fehler möglicherweise entdeckt, da Sie die Referenz BLEDiscovery hätten abrufen müssen, bevor Sie auf das Array zugegriffen haben und eine Array-Begrenzungsausnahme als Array ausgelöst hätten wäre leer gewesen.

können Sie restrukturieren Ihre BLEDiscovery ein Singleton zu sein und beseitigen die Globals:

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 

Nun, wenn Sie die Instanz von BLEDiscovery möchten, können Sie BLEDiscovery.sharedInstance verwenden z.B.

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 

    } 

} 
+0

Danke für die Rückmeldung. Ich werde Ihre Empfehlungen später aktualisieren und testen. Sie waren eine große Hilfe, ich dachte konzeptionell, was falsch war, aber ich konnte es nicht sehen ... – user5308141

+0

Eine weitere Frage, hätte dies Auswirkungen auf einen Delegierten bei BLEDiscovery? – user5308141

+0

Ja, Delegierte und Singletons sind keine gute Mischung. Ich würde NSNotification verwenden, da Sie eine beliebige Anzahl von Abonnenten haben können – Paulw11

Verwandte Themen