centralManager didConnectPeripheral 永远不会被调用
centralManager didConnectPeripheral is never called
我一直在研究一段代码,用于从 table 连接 BLE 设备。我能够发现设备并将它们加载到 table 中。在 table 中的行选择中,我请求连接所选设备。但是,永远不会调用 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()
}
}
我知道正在从 table 调用代码,因为我可以在日志 window.
中观察到 "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
}
}
像你的BLEDiscovery
这样的对象最好作为单例实现,或者你可以使用Dependency Injection,但主要的是要有一个class的实例。
您正在使用全局变量来实现这一点,但您在 didSelectRowAtIndexPath
函数中失误了。当你说
case .Connected:
//Disconnect as device is connected
BLEDiscovery().disconnectBLEDevice(peripheral)
您创建了一个新的本地 BLEDiscovery
实例,其中包含自己的 CBCentralManager
,这是您要求执行连接的中心。一旦退出 case 语句,这个局部 BLEDiscovery
将被释放,因此永远不会调用委托方法。如果您将外围设备数组封装在 BLEDiscovery
class 中而不是使用全局数组,您可能会发现此错误,因为您必须在访问数组之前获取 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
}
}
我一直在研究一段代码,用于从 table 连接 BLE 设备。我能够发现设备并将它们加载到 table 中。在 table 中的行选择中,我请求连接所选设备。但是,永远不会调用 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()
}
}
我知道正在从 table 调用代码,因为我可以在日志 window.
中观察到 "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
}
}
像你的BLEDiscovery
这样的对象最好作为单例实现,或者你可以使用Dependency Injection,但主要的是要有一个class的实例。
您正在使用全局变量来实现这一点,但您在 didSelectRowAtIndexPath
函数中失误了。当你说
case .Connected:
//Disconnect as device is connected
BLEDiscovery().disconnectBLEDevice(peripheral)
您创建了一个新的本地 BLEDiscovery
实例,其中包含自己的 CBCentralManager
,这是您要求执行连接的中心。一旦退出 case 语句,这个局部 BLEDiscovery
将被释放,因此永远不会调用委托方法。如果您将外围设备数组封装在 BLEDiscovery
class 中而不是使用全局数组,您可能会发现此错误,因为您必须在访问数组之前获取 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
}
}