ios - 蓝牙扫描启动 SwiftUI 后渲染列表

标签 ios swift bluetooth swiftui

我正在尝试使用 SwiftUI 制作蓝牙扫描和连接应用程序。当蓝牙扫描开始时,我在刷新 SwiftUI 中的 ListView 时遇到问题,我得到了一些具有 RSSI 值的外围设备名称。任何指导都会很有用。代码如下:

首先,我有一个 SwiftUI View ,其中包含一个列表和 Horizo​​ntalView 中的文本。稍后我将使用 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 列表的范围内进出时显示它们。 谢谢。

最佳答案

你这里没有状态,也没有办法更新那个状态。我可能会将 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 中自动更新。

关于ios - 蓝牙扫描启动 SwiftUI 后渲染列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58239721/

相关文章:

iphone - 可以使用 popViewController Animated 传递数据吗?

ios - 单击按钮以编程方式切换 UIViewControllers

ios - OSX蓝牙LE外围设备的传输速度很慢

Android 应用程序的蓝牙 BLE 扫描在广告停止时停止。为什么?

java - 是否可以通过蓝牙从麦克风接收音频并从设备播放音频?

ios - 我发现了一个僵尸..现在怎么办?

ios - 如何实现云代码?

ios - 分组条形图上的 X 轴值

ios - 无法执行方法--错误 :Value of type 'UITableViewCell' has no member 'getCell'

swift - 如何在 SwiftUI 中暂停动画?