I'd like to capture the progress value in a VNRecognizeTextRequest session. So I inclueded it in a closure. The problem is it is passed when the closure is completed. I can capture the value and print it but not pass it to the main thread to update my progress bar. So I pass from 0% to 100% in the main thread. Can anybody give me a hand please? Thanks a lot. Here's my code.
private func readImage(image:UIImage, completionHandler:@escaping(([VNRecognizedText]?,Error?)->Void), comp:@escaping((Double?,Error?)->())) {
var recognizedTexts = [VNRecognizedText]()
let requestHandler = VNImageRequestHandler(cgImage: (image.cgImage)!, options: [:])
let textRequest = VNRecognizeTextRequest { (request, error) in
guard let observations = request.results as? [VNRecognizedTextObservation] else { completionHandler(nil,error)
return
}
for currentObservation in observations {
let topCandidate = currentObservation.topCandidates(1)
if let recognizedText = topCandidate.first {
recognizedTexts.append(recognizedText)
}
}
completionHandler(recognizedTexts,nil)
}
textRequest.recognitionLevel = .accurate
textRequest.recognitionLanguages = ["es"]
textRequest.usesLanguageCorrection = true
textRequest.progressHandler = {(request, value, error) in
print(value)
comp(value,nil)
}
try? requestHandler.perform([textRequest])
}
This is how I call my function from the content view.
struct ContentView: View {
@State var ima = drawPDFfromURL(url: dalai)
@State private var stepperCounter = 0
@State private var observations = [VNRecognizedText]()
@State private var progressValue: Float = 0.0
private var originaImage = drawPDFfromURL(url: dalai)
var body: some View {
VStack { Button(action: {
//self.observations = readText(image: self.ima!)
DispatchQueue.main.async {
readImage(image: self.ima!, completionHandler: { (texts, error) in
self.observations = texts!
}) { (value, err) in
self.progressValue = Float(value!)
}
}
})
{
Text("Read invoice")
}
ProgressBar(value: $progressValue).frame(height: 20)
}.padding()
}
}
This is my ProgressBar object
struct ProgressBar: View {
@Binding var value: Float
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Rectangle().frame(width: geometry.size.width , height: geometry.size.height)
.opacity(0.3)
.foregroundColor(Color(UIColor.systemTeal))
Rectangle().frame(width: min(CGFloat(self.value)*geometry.size.width, geometry.size.width), height: geometry.size.height)
.foregroundColor(Color(UIColor.systemBlue))
.animation(.linear)
}.cornerRadius(45)
}
}
}