我正在尝试使用SwiftUI进行蓝牙扫描并连接应用程序。蓝牙扫描开始时,我在刷新SwiftUI中的列表视图时遇到问题,并且得到了一些带有RSSI值的外设名称。任何指导都是有用的。代码如下:
首先,我有一个SwiftUI视图,其中包含列表和其中的HorizontalView中的文本。稍后我将使用ForEach(),但现在我只用一个文本就保持了简单性。
import SwiftUI
struct ContentView: View {
var body: some View {
List{
// ForEach: Loop here to list all BLE Devices in "devices" array
// Monitor "devices" array for changes. As changes happen, Render the Body again.
HStack{
Text("Device-1")
.onTapGesture {
// To Do: Call Connect BLE Device
print("Device-1 Connected.")
}
}
}.navigationBarTitle("BLE Devices")
.onAppear(perform: connectBLEDevice)
}
private func connectBLEDevice(){
let ble = BLEConnection()
// Start Scanning for BLE Devices
ble.startCentralManager()
}
}
// UIHosting Controller
var child = UIHostingController(rootView: ContentView())
这是我使用的用于扫描并连接到蓝牙设备的代码:
import Foundation
import UIKit
import CoreBluetooth
open class BLEConnection: NSObject, CBPeripheralDelegate, CBCentralManagerDelegate {
// Properties
private var centralManager: CBCentralManager! = nil
private var peripheral: CBPeripheral!
public static let bleServiceUUID = CBUUID.init(string: "XXXX")
public static let bleCharacteristicUUID = CBUUID.init(string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX")
// Array to contain names of BLE devices to connect to.
// Accessable by ContentView for Rendering the SwiftUI Body on change in this array.
var scannedBLEDevices: [String] = []
func startCentralManager() {
self.centralManager = CBCentralManager(delegate: self, queue: nil)
print("Central Manager State: \(self.centralManager.state)")
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.centralManagerDidUpdateState(self.centralManager)
}
}
// Handles BT Turning On/Off
public 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("Central scanning for", BLEConnection.bleServiceUUID);
self.centralManager.scanForPeripherals(withServices: [BLEConnection.bleServiceUUID],options: [CBCentralManagerScanOptionAllowDuplicatesKey : true])
break
}
if(central.state != CBManagerState.poweredOn)
{
// In a real app, you'd deal with all the states correctly
return;
}
}
// Handles the result of the scan
public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print("Peripheral Name: \(String(describing: peripheral.name)) RSSI: \(String(RSSI.doubleValue))")
// We've found it so stop scan
self.centralManager.stopScan()
// Copy the peripheral instance
self.peripheral = peripheral
self.scannedBLEDevices.append(peripheral.name!)
self.peripheral.delegate = self
// Connect!
self.centralManager.connect(self.peripheral, options: nil)
}
// The handler if we do connect successfully
public func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
if peripheral == self.peripheral {
print("Connected to your BLE Board")
peripheral.discoverServices([BLEConnection.bleServiceUUID])
}
}
// Handles discovery event
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let services = peripheral.services {
for service in services {
if service.uuid == BLEConnection.bleServiceUUID {
print("BLE Service found")
//Now kick off discovery of characteristics
peripheral.discoverCharacteristics([BLEConnection.bleCharacteristicUUID], for: service)
return
}
}
}
}
// Handling discovery of characteristics
public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if let characteristics = service.characteristics {
for characteristic in characteristics {
if characteristic.uuid == BLEConnection.bleServiceUUID {
print("BLE service characteristic found")
} else {
print("Characteristic not found.")
}
}
}
}
}
这里的任务是扫描外围设备,并显示它们在SwiftUI列表中的进出范围。 谢谢。
答案 0 :(得分:2)
您在这里没有状态,也无法更新该状态。我可能会将BLEConnection
设为ObservableObject
,然后将@Publish
设为设备数组:
open class BLEConnection: ..., ObservableObject {
@Publish var scannedBLEDevices: [Device] = [] // keep as [String] for initial debugging if you want
}
然后在您的ContentView
中订阅这些更改:
struct ContentView: View {
@ObservedObject var bleConnection = BLEConnection()
var body: some View {
// if still `[String]` then \.self will work, otherwise make `Device` `Identifiable`
List(bleConnection.devices, id: \.self) { device in
Text(verbatim: device)
}
}
}
现在,当您的连接将设备添加/删除到scannedBLEDevices
时,它将在您的ContentView
中自动更新。