Как ждать обратного вызова BLE без блокировки кода - PullRequest
0 голосов
/ 29 мая 2019

Я пытаюсь обмениваться данными между двумя устройствами BLE. На самом деле клиентская сторона функционирует, и моя проблема на стороне сервера на телефоне IOS. Я создаю контроллер BluetoothLEC, который наследуется от NSObject и CBPeripheralManagerDelegate. Все запчасти для услуг, рекламы, связи, подписки и didReceiveWrite работ.

Моя проблема в том, что когда я вызываю метод updateValue класса CBPeripheralManager дважды или более в одно и то же время, только первый вызов завершился успешно. В документации Swift эта функция возвращает false, если очередь отправки занята. Я кодирую псевдо бесконечный цикл, как это

while !peripheralManager.updateValue(data,
                                     for: messageContentCharacteristic,
                                     onSubscribedCentrals: nil) {}

Это работает, но это действительно плохая реализация!

Итак, после этого я попытался использовать DispatchSemaphore

let semaphore = DispatchSemaphore(value: 1)
func write(_ data: Data) {
    DispatchQueue.global().async {
        self.semaphore.wait()
        self.peripheralManager.updateValue(data,
                                           for: self.messageContentCharacteristic,
                                           onSubscribedCentrals: nil)
    }
}

func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
    semaphore.signal()
}

Все темы запущены. Первый звонок updateValue и мой клиент получает уведомление. Другие ждут. Но обратный вызов peripheralManagerIsReady#toUpdateSubscribers никогда не вызывается, и мое приложение блокируется.

Я пытаюсь по-другому с DispatchGroup и DispatchQueue с другим приоритетом, но моя проблема остается той же.

Я надеюсь, что кто-то может помочь мне стать лучшим разработчиком :)

1 Ответ

0 голосов
/ 03 июня 2019

Как говорит Paulw11, я реализую общую очередь на основе Swift Algorithm Club. Я использую свой семафор, но только для поточной защиты.

let queue = Queue<Data>()
let semaphore = DispatchSemaphore(value: 1)

func write(_ data: Data) {
    if !peripheralManager.updateValue(data,
                                  for: messageContentCharacteristic,
                                  onSubscribedCentrals: nil) {
        semaphore.wait()
        queue.enqueue(data)
        semaphore.signal()
    }
}

func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
    if !queue.isEmpty {
        semaphore.wait()
        if let data = queue.dequeue() {
            peripheralManager.updateValue(data,
                                          for: messageContentCharacteristic,
                                          onSubscribedCentrals: nil)
        }
        semaphore.signal()
    }
}
...