所以我目前在 iPad 和 iPhone 之间设置了蓝牙连接。我在 ViewController 中创建了我的测试代码,一切正常。现在我将它移到了 2 个管理器类,一个用于 CBCentralManager ,一个用于 CBPeripheralManager 上面的那些我制作了一个 BluetoothManager 的类,这是一个单例类并保存有关当前连接设备的一些信息。
但是,当我这样做时,我遇到了一个问题,似乎 centralManager.connect() 调用实际上不起作用。我调试了我的整个代码,在那一行之后似乎什么都没有发生,我似乎无法弄清楚为什么会这样或者我实际上哪里出错了。
CentralManager 类
import Foundation
import CoreBluetooth
class CentralManager: NSObject {
private var centralManager: CBCentralManager!
var peripherals: [CBPeripheral] = []
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
}
// MARK: - CBCentralManager Delegate Methods
extension CentralManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
centralManager.scanForPeripherals(withServices: [BLEConstants.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
default:
break
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if !peripherals.contains(peripheral) {
peripheral.delegate = self
peripherals.append(peripheral)
centralManager.connect(peripheral, options: nil)
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheral.discoverServices([BLEConstants.serviceUUID])
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
guard let peripheralIndex = peripherals.index(of: peripheral), BluetoothManager.shared.deviceCharacteristic[peripheral] != nil else { return }
peripherals.remove(at: peripheralIndex)
BluetoothManager.shared.deviceCharacteristic.removeValue(forKey: peripheral)
}
}
// MARK: - CBPeripheral Delegate Methods
extension CentralManager: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service in peripheral.services! {
if service.uuid == BLEConstants.serviceUUID {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
let characteristic = characteristic as CBCharacteristic
if BluetoothManager.shared.deviceCharacteristic[peripheral] == nil {
BluetoothManager.shared.deviceCharacteristic[peripheral] = characteristic
}
}
}
func peripheral(_ peripheral: CBPeripheral, didModifyServices invalidatedServices: [CBService]) {
}
}
PeripheralManager 类
class PeripheralManager: NSObject {
private var peripheralManager: CBPeripheralManager!
override init() {
super.init()
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
}
}
// MARK: - Manage Methods
extension PeripheralManager {
func updateAdvertising() {
guard !peripheralManager.isAdvertising else { peripheralManager.stopAdvertising(); return }
let advertisingData: [String: Any] = [CBAdvertisementDataServiceUUIDsKey: BLEConstants.serviceUUID,
CBAdvertisementDataLocalNameKey: BLEConstants.bleAdvertisementKey]
peripheralManager.startAdvertising(advertisingData)
}
func initializeService() {
let service = CBMutableService(type: BLEConstants.serviceUUID, primary: true)
let characteristic = CBMutableCharacteristic(type: BLEConstants.charUUID, properties: BLEConstants.charProperties, value: nil, permissions: BLEConstants.charPermissions)
service.characteristics = [characteristic]
peripheralManager.add(service)
}
}
// MARK: - CBPeripheralManager Delegate Methods
extension PeripheralManager: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
initializeService()
updateAdvertising()
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
for request in requests {
if let value = request.value {
let messageText = String(data: value, encoding: String.Encoding.utf8)
print(messageText ?? "")
}
self.peripheralManager.respond(to: request, withResult: .success)
}
}
}
BluetoothManager 类
class BluetoothManager {
static let shared = BluetoothManager()
private var centralManager: CentralManager!
private var peripheralManager: PeripheralManager!
var deviceCharacteristic: [CBPeripheral: CBCharacteristic] = [:]
var connectedPeripherals: [CBPeripheral] { return centralManager.peripherals }
func setup() {
centralManager = CentralManager()
peripheralManager = PeripheralManager()
}
}
然后在我的 ViewController didLoad 我正在调用 BluetoothManager.shared.setup()
有谁知道为什么这些设备似乎没有相互连接,或者之后的委托(delegate)函数没有被调用?
Best Answer-推荐答案 strong>
当使用 BluetoothManager() 初始化静态 shared 变量时,该过程开始。我不确定在 Swift 中何时会发生这种情况,它要么是在程序的一开始,要么是在您第一次使用 BluetoothManager.setup 时。
变量的初始化调用BluetoothManager 的init() 方法。这将实例化一个 CentralManager ,并调用它的 init() 方法。这将实例化一个 CBCentralManager ,它将启动蓝牙进程。
然后你调用setup() ,它会实例化一个新的CentralManager ,有它自己的CBCentralManager 。我可以想象两个 CBCentralManager 出了点问题。
要解决它,不要使用setup() ,而是在init() 中初始化变量。
要调试这种情况,请在所有 init() 方法中放置断点。创建析构函数,并在其中放置断点。从技术上讲,无论如何您都需要析构函数,因为您需要从 CBCentralManager 对象中删除自己作为委托(delegate)。
还要注意,您只能从 centralManagerDidUpdateState 调用 scanForPeripherals 。 CBCentralManager 在启动时可能已经处于 poweredOn 状态,这可能发生在另一个应用同时使用蓝牙时 - 或者当您的第一个 CBCentralManager 对象已经启动它。在这种情况下,将永远不会调用 centralManagerDidUpdateState 。
关于ios - CoreBluetooth 功能在 Singleton 中不起作用,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/51771422/
|