SwiftUI: как обрабатывать ответ BLE и отображать новые значения - PullRequest
2 голосов
/ 25 мая 2020

У меня есть быстрое приложение, которое взаимодействует с небольшим устройством BLE. Я могу отправлять запросы и получать ответы с устройства, но мне трудно обновлять значения, отображаемые в моем представлении swiftui.

Вот что я пробовал:

  1. С обратным вызовом:

В файле BleConnection.swift, реализующем все материалы BLE, я объявил обратный вызов var onResponse: (([UInt8]) -> Void)? = nil Когда от устройства получен ответ, данные передаются в представление с помощью обратного вызова:

    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
...
            if self.onResponse != nil {
                    self.onResponse!(characteristic.value!.bytes)
                }
            }
        }
    }

В файле ReaderInformations.swift, где есть представление swiftui, я реализовал обратный вызов и попытался обновить отображаемое значение компонента с помощью @State var, но это не сработало. Print () в обратном вызове хорошо печатается в консоли, но компонент не обновляется. Затем я прочитал, что только внутренний метод представления может обновить переменную состояния.

С помощью Combine: я обновил периферийное устройство (didUpdateValueFor) и отправил ответ устройства BLE следующим образом:
let passThroughSubjectPublisher = PassthroughSubject<[UInt8], Never>()

    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
...
            passThroughSubjectPublisher.send(characteristic.value!.bytes)  
        }
    }

и в представлении:

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)
    }

Я не тоже не работает, потому что я пытался в инициализации получить доступ к члену, который еще даже не был создан.

Итак, я не знаю, как это сделать. Как бы вы с этим справились?

1 Ответ

1 голос
/ 25 мая 2020

Вместо этого прикрепите наблюдателя издателя в теле, как в псевдокоде ниже

struct ReaderInformations: View {
    var ble: BleConnection
    @State private var status: String = "status" 

    var body: some View {

       VStack { // .. any your view


       }
       .onReceive(ble.passThroughSubjectPublisher) { response in // << here !!
              switch response[0] {
                 self.status = "TEST"
              ///...
             }
        }
    }
}
...