3

I have a problem and I really don't know how to solve it. I'm developing an app which uses Vision/VisionKit and every time I push on the button to run the camera in order to take a picture and scan the text, it takes memory. So, every time I press the button for the camera, memory will always increase.

My app crashes when it reaches up 1 gb of memory (after 9, 10 scans more or less). This is the Xcode Alert:

The App "xxx" quit unexpectedly. Message from debugger: Terminated due to memory issue.

In addition, when I take the picture and the app scans the text of that pic, I pass the data (the text) to another ViewController by clicking on the button "CopyText", but it seems that it doesn't free the memory or dismiss the previous view. It looks like VNDocumentCameraViewController is always open in background (I think). I have never encountered this problem, but now it is happening. Any suggestion?

P.s.: I was curious and I tried to use the native app "Note" on my iPhone. After 13-14 scans, the app crashed and it resprang my device. I'm going crazy. Is this normal, then?

This is my code. I am hopeless

import UIKit
import Vision
import VisionKit


class ScanText: UIViewController, VNDocumentCameraViewControllerDelegate {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var TextScan: UITextView!
    @IBOutlet weak var buttonStartShape: UIButton!
    @IBOutlet weak var infoScattaUnaFoto: UILabel!
    @IBOutlet weak var copyButtonShape: UIButton!
    @IBOutlet weak var thisIsAPreviewLabel: UILabel!
    
    var textRecognitionRequest = VNRecognizeTextRequest(completionHandler: nil)
    private let textRecognitionWorkQueue = DispatchQueue(label: "MyVisionScannerQueue", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)
    
    var classView = ViewController()
    var arrayText = String()
    let notificationGenerator = UINotificationFeedbackGenerator()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.imageView.layer.cornerRadius = 20
        self.imageView.clipsToBounds = true
        
    }
    override func viewWillAppear(_ animated: Bool) {
        thisIsAPreviewLabel.isHidden = true
        TextScan.layer.cornerRadius = 15
        TextScan.clipsToBounds = true
        
        copyButtonShape.layer.cornerRadius = 25
        copyButtonShape.clipsToBounds = true
        
        buttonStartShape.layer.cornerRadius = 25
        buttonStartShape.clipsToBounds = true
        
        TextScan.isEditable = false
        setupVision()
        
    }
    

    @IBAction func TakePicture(_ sender: Any) {
        let scannerViewController = VNDocumentCameraViewController()
        scannerViewController.delegate = self
        self.imageView.layer.cornerRadius = 20
        self.imageView.clipsToBounds = true
        self.infoScattaUnaFoto.isHidden = true
        present(scannerViewController, animated: true)
        
    }
    
    
    private func setupVision() {
   
        textRecognitionRequest = VNRecognizeTextRequest { (request, error) in
            guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
            
            var detectedText = ""
            for observation in observations {
                guard let topCandidate = observation.topCandidates(2).first else { return }
                print("text \(topCandidate.string) has confidence \(topCandidate.confidence)")
                
                
                detectedText += topCandidate.string
                detectedText += "\n"
                
                
            }
            
            DispatchQueue.main.async {
                self.thisIsAPreviewLabel.isHidden = false
                self.TextScan.isHidden = false
                
                self.copyButtonShape.isHidden = false
                self.buttonStartShape.setTitle("Retake", for: .normal)
                self.TextScan.text += detectedText
                
                self.TextScan.flashScrollIndicators()
                
            }
        }
        
        textRecognitionRequest.recognitionLevel = .accurate
    }
    private func processImage(_ image: UIImage) {
        imageView.image = image
        recognizeTextInImage(image)
    }
    
    private func recognizeTextInImage(_ image: UIImage) {
        guard let cgImage = image.cgImage else { return }
        
        TextScan.text = ""
        textRecognitionWorkQueue.async {
            let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
            do {
                try requestHandler.perform([self.textRecognitionRequest])
            } catch {
                print(error)
            }
        }
    }
    func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
        /* guard scan.pageCount >= 1 else {
         controller.dismiss(animated: true)
         return
         }*/
        for i in 0 ..< scan.pageCount {
            let img = scan.imageOfPage(at: i)
            processImage(img)
            
        }
        
        let originalImage = scan.imageOfPage(at: 0)
        print(originalImage)
        //let newImage = compressedImage(originalImage)
        controller.dismiss(animated: true, completion: nil)
        
        
    }
    
    func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) {
        print(error)
        
        controller.dismiss(animated: true, completion: nil)
    }
    
    func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
        controller.dismiss(animated: true, completion: nil)
    }
    
    func compressedImage(_ originalImage: UIImage) -> UIImage {
        guard let imageData = originalImage.jpegData(compressionQuality: 1),
              let reloadedImage = UIImage(data: imageData) else {
            return originalImage
        }
        return reloadedImage
    }
    //MARK: By tapping on this button, I pass all the data.
    
    @IBAction func CopyText(_ sender: Any) {
        if TextScan.text.isEmpty {
            hapticTapped()
        
 
            let alertController = UIAlertController(title: "Error", message:
                                                        "It's impossible to copy. Your text view is empty", preferredStyle: .alert)
            alertController.addAction(UIAlertAction(title: "Ok", style: .default))
            
            self.present(alertController, animated: true, completion: nil)
        }else{
            
            self.dismiss(animated:true, completion: nil)
            
            let vc = (storyboard?.instantiateViewController(identifier: "SpeakDetail") as? ViewController)!
            
            vc.textscannerized = TextScan.text
            
            self.navigationController?.pushViewController(vc, animated: true)
            
    
        }
        
    }
    
    func hapticTapped() {
        notificationGenerator.notificationOccurred(.error)
    }
      
}
TylerP
  • 9,600
  • 4
  • 39
  • 43
swishG
  • 61
  • 2

0 Answers0