Search code examples
swiftcore-bluetooth

Asynchronous Swift issues


I am a Javascript developer poking around in Swift and am having a hard time migrating an example Playground app I found (https://github.com/gregiOS/Playgrounds/tree/master/BLE.playground) to a CLI app.

import Cocoa
import PlaygroundSupport

let tableViewController = TableViewController()
let dataSource = tableViewController.dataSource

PlaygroundPage.current.liveView = tableViewController.view

let scanner = BluetoothScanner { scanner in
    scanner.startScanning { (peripheral) in
        print("Discovered peripheral: \(peripheral.tableViewData)")
    }
}

My desire, and what I tried is to just remove import PlaygroundSupport and the dataSource/tableViewController stuff and just have the peripherals printed out to stdout, however the program just exits immediately. I tried using a dispatch group, but that didn't seem to work either:

import Cocoa

let myGroup = DispatchGroup()

print("Scanning...")
myGroup.enter()

let scanner = BluetoothScanner { scanner in
  scanner.startScanning { (peripheral) in
    print("Discovered peripheral: \(peripheral.tableViewData)")
    myGroup.leave()
  }
}

myGroup.notify(queue: .main) {
  print("Finished all requests.")
}

Also tried using myGroup.wait() but it just sat there doing nothing. I believe part of the problem is that the scan runs indefinitely, whereas I just need it to run for 2 seconds or so and stop.

Point is, I'm in over my head and need to create a PoC showing Bluetooth discovery. I would greatly appreciate any pointers.


Solution

  • To run asynchronous stuff in a CLI you need a runloop

    let runLoop = CFRunLoopGetCurrent()
    print("Scanning...")
    
    let scanner = BluetoothScanner { scanner in
      scanner.startScanning { (peripheral) in
        print("Discovered peripheral: \(peripheral.tableViewData)")
        CFRunLoopStop(runLoop)
      }
    }
    
    CFRunLoopRun()