Функция UIKeyInput deleteBackward() аварийно завершает работу из-за одновременного вызова insertText()

Я пишу приложение для машинного обучения, которое действует как клавиатура. Оно используетUIKeyInput и .target.insertText()метод для вставки результатов машинного обучения. Я реализовал ключ удаления, используяtarget?.deleteBackward()и имеют периодические сбои из-за того, что мои выходные данные машинного обучения могут запускаться одновременно с нажатием клавиши удаления. Я пробовал реализовать семафоры так:

let semaphoreDelete = DispatchSemaphore(value: 1)
func didOutput(pixelBuffer: CVPixelBuffer) {
    let currentTimeMs = Date().timeIntervalSince1970 * 1000
    guard (currentTimeMs - previousInferenceTimeMs) >= delayBetweenInferencesMs else { return }
    previousInferenceTimeMs = currentTimeMs
    // Pass the pixel buffer to TensorFlow Lite to perform inference.
    result = modelDataHandler?.runModel(onFrame: pixelBuffer)
    DispatchQueue.main.async {
    self.semaphoreDelete.wait()
    self.prediction = [
      "\(self.result!.inferences[0].label.description) : \(self.result!.inferences[0].confidence.description)",
      "\(self.result!.inferences[1].label.description) : \(self.result!.inferences[1].confidence.description)",
      "\(self.result!.inferences[2].label.description) : \(self.result!.inferences[2].confidence.description)"
    ]
    if (self.result?.inferences[0].confidence)! >= 0.99 {
        self.insertMachineLearningOutput()
        self.semaphoreDelete.signal()
    }
    }
    // Display results by handing off to the InferenceViewController.
    DispatchQueue.main.async {
        let resolution = CGSize(width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))
    }
}
//checks machine learning output for command or character to insert
private func insertMachineLearningOutput() {
    switch self.result?.inferences[0].label {
    case "del":
    self.target?.deleteBackward()
    case "space":
    self.semaphoreDelete.signal()
    self.target?.insertText(" ")
    case "nothing":
    break
    default:
    self.target?.insertText(self.result!.inferences[0].label.description)
    }
}

Я также добавил семафор в мой метод удаления, который вызывается с клавиатуры:

    @objc func deleteChar(completion:@escaping () -> Void) {
        DispatchQueue.main.async {
            self.semaphoreDelete.wait()
            self.target?.deleteBackward()
            self.semaphoreDelete.signal()
        }

    }

Кажется, что приложение заходит в тупик, когда я реализую такие семафоры... Должен быть какой-то способ сигнализировать функции удаления, чтобы ей не разрешалось срабатывать, когда модель ML вставляет текст?

ОБНОВЛЕНИЕ... Итак, я попытался использовать DispatchGroups, потому что использование семафоров не имеет смысла, поскольку обе задачи находятся в основном потоке.

let MLDispatchGroup = DispatchGroup()
func didOutput(pixelBuffer: CVPixelBuffer) {
  let currentTimeMs = Date().timeIntervalSince1970 * 1000
  guard (currentTimeMs - previousInferenceTimeMs) >= delayBetweenInferencesMs else { return }
  previousInferenceTimeMs = currentTimeMs

  // Pass the pixel buffer to TensorFlow Lite to perform inference.
  result = modelDataHandler?.runModel(onFrame: pixelBuffer)

  MLDispatchGroup.enter()
  DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    //This block takes the model output and inserts it to the 
    // UITextView
    switch self.result?.inferences[0].label {
    case "del":
      self.target?.deleteBackward()
    case "space":
      self.target?.insertText(" ")
    case "nothing":
      break
    default:
      self.target?.insertText(self.result!.inferences[0].label.description)
    }
    // Display results by handing off to the InferenceViewController.
    let resolution = CGSize(width: CVPixelBufferGetWidth(pixelBuffer), height: CVPixelBufferGetHeight(pixelBuffer))
    self.MLDispatchGroup.leave()
  }
  MLDispatchGroup.notify(queue: DispatchQueue.main) {
    print("should be doing ML")
  }
}
@objc func deleteChar(completion:@escaping () -> Void) {
  MLDispatchGroup.enter()
  DispatchQueue.main.asyncAfter(deadline: .now()) {
    self.target?.deleteBackward()
    self.MLDispatchGroup.leave()
  }
  MLDispatchGroup.notify(queue: DispatchQueue.main) {
    print("should be deleting")
  }
}

0 ответов

Другие вопросы по тегам