title: Render List after Bluetooth Scanning starts SwiftUI
body: <p>I am trying to make a Bluetooth scanning and connect app using SwiftUI. I am having issues refreshing the list view in SwiftUI as the Bluetooth scanning starts and I get some peripheral names with RSSI values. Any guidance would be useful. The code is as follows:</p>
  
  <p>Firstly I have a SwiftUI view with a list and the text in HorizontalView within that. I will be using ForEach() later on but for now I just kept it simple with one text.</p>
  
  <pre><code>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())
  </code></pre>
  
  <p>For scanning and connecting to the Bluetooth device, this is the code that I use:</p>
  
  <pre><code>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.")
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>The task here is to scan for peripherals and show them as they come and go from the range in the SwiftUI List.
  Thanks.</p>