I have a swift application that communicates with a small BLE device. I'm able to send requests and get answers from the device but I struggle updating values displayed on my swiftui view.
Here's what I tried:
- With a callback:
In the BleConnection.swift file, implementing all BLE stuff, I declared a callback var onResponse: (([UInt8]) -> Void)? = nil
When a response is received from the device, the data is pushed to the view with the callback:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
...
if self.onResponse != nil {
self.onResponse!(characteristic.value!.bytes)
}
}
}
}
In the ReaderInformations.swift file, where there is the swiftui view, I implemented the callback and tried to update a component displayed value with a @State var but it didn't work out. The print() in the callback is well printed in the console but the component not updated. I then read that only internal method to the view could update a state var.
- With Combine: I updated the peripheral(didUpdateValueFor) and sent the BLE device response like this:
let passThroughSubjectPublisher = PassthroughSubject<[UInt8], Never>()
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
...
passThroughSubjectPublisher.send(characteristic.value!.bytes)
}
}
and in the view:
struct ReaderInformations: View {
var ble: BleConnection
@State private var status: String = "status"
private var cancelSet: Set<AnyCancellable> = []
init(bleInstance: BleConnection) {
passThroughSubjectPublisher.sink(receiveValue: { response in. // Escaping closure captures mutating 'self' parameter
switch response[0] {
self.status = "TEST". // This error because of the self
...
}
}).store(in: &cancelSet)
}
I doesn't work either, because I tried in the init to access a member not even instantiated yet.
So here I am with no idea how to do. How would you guys manage this?