Moaz Khan Moaz Khan - 3 months ago 19
iOS Question

How to handle Fatal Error in Tesseract OCR 4.0 iOS Swift

I am using Tesseract OCR in my app. For gallery images it's working fine if I use a very clear image such as this one
5 text image

But for some images it gives me an error and the app crashes in my iPhone. App almost always crashes when I use a camera image as well. Now I want to know how to handle FATAL Error in Swift 2.2 . How can I show an alert that image was unreadable instead of crashing my app. I tried do {} catch {} but it doesn't work.

func checkWithOCR() throws{

let ocrSample = myImageView.image //image picker from gallery

//FATAL ERROR ON THIS LINE.
tesseract.image = ocrSample!.fixOrientation().g8_blackAndWhite()
if(tesseract.recognize()){
let recognizedText = tesseract.recognizedText
if recognizedText != nil{
print("recognizedText: \(recognizedText)")

let trimmedText = String(recognizedText.characters.filter { !" \n\t\r,".characters.contains($0) })
myImageView.image = tesseract.image
convertCurrency(Float(trimmedText)!) //convert the tesseract text
}
}

SwiftSpinner.hide()
}


HERE IS THE ERROR:
recognizedText:
fatal error: unexpectedly found nil while unwrapping an Optional value

I know why this error occurs as there was no value on the line I mentioned above. How can I show an alert box if this error occurs instead of a crash.

P.S: I tried if ( ocrSample!.fixOrientation().g8_blackAndWhite() != nil ) {}


It doesn't work

Answer

The image on a UIImageView is an UIImage optional, meaning that it can have a value (contain an image) or it can be nil.

So, when you're saying:

let ocrSample = myImageView.image

your ocrSample is now an UIImage optional, which you then have to unwrap before you use it.

When you then say:

tesseract.image = ocrSample!.fixOrientation().g8_blackAndWhite()

you are force unwrapping your ocrSample by using !, meaning that you are telling the compiler to just unwrap and use the optional, regardless of it being nil or not. This causes a crash when you then try to use that unwrapped optional if it contains nil.

What you can do is unwrap ocrSample using an if let like so:

func checkWithOCR() throws{

    if let ocrSample = myImageView.image {
        tesseract.image = ocrSample.fixOrientation().g8_blackAndWhite() 
        if(tesseract.recognize()){
            let recognizedText = tesseract.recognizedText
            if recognizedText != nil{
                print("recognizedText: \(recognizedText)")

                let trimmedText = String(recognizedText.characters.filter { !" \n\t\r,".characters.contains($0) })
                myImageView.image = tesseract.image
                convertCurrency(Float(trimmedText)!) //convert the tesseract text
            }
        }
        SwiftSpinner.hide()
    } else {
        //No value could be found, do your error handling here
    }
}

Here:

if let ocrSample = myImageView.image

you are trying to unwrap the value of myImageView.image into ocrSample, if that succeeds, then you now for sure that ocrSample is not nil and can use it onwards. If it fails, then you can do your error handling, show an alert view and whatever else you need to do.

Hope that helps you.