I used to be studying by this weblog, as I’ve an identical use-case: https://kelvas09.github.io/weblog/posts/closure-delegate-to-async/
I observed the next snippet:
actor BluetoothLEScanWrapper {
enum BluetoothLEScanError: Error {
case bluetoothNotAvailable
}
non-public let bluetoothLEDelegate: BluetoothLEDelegate = BluetoothLEDelegate()
non-public var activeTask: Process<[BluetoothLEDevice], Error>?
func scan(for seconds: Double = 3.0) async throws -> [BluetoothLEDevice] {
if let existingTask = activeTask {
return attempt await existingTask.worth
}
let process = Process<[BluetoothLEDevice], Error> {
guard bluetoothLEDelegate.bluetoothIsOn else {
activeTask = nil
throw BluetoothLEScanError.bluetoothNotAvailable
}
self.bluetoothLEDelegate.central.scanForPeripherals(withServices: nil)
attempt await Process.sleep(nanoseconds: (UInt64(seconds) * 1_000_000_000))
let gadgets = bluetoothLEDelegate.foundPeripheral.compactMap { BluetoothLEDevice(peripheral: $0) }
bluetoothLEDelegate.central.stopScan()
bluetoothLEDelegate.foundPeripheral = []
activeTask = nil
return gadgets
}
activeTask = process
return attempt await process.worth
}
...
The creator particularly calls consideration to using actor. As I perceive it, that is to keep away from knowledge races with activeTask
in case scan()
is named repeatedly. Is my understanding appropriate? Thanks for the assistance.