Я пишу приложение для машинного обучения, которое работает как клавиатура. Он использует 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)
}
}
Я также добавил семафор в метод my delete, который вызывается с клавиатуры:
@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")
}
}