首页 > 解决方案 > Swift App:“VNDocumentCameraViewController”如何通过关闭 ViewController 来释放内存?

问题描述

我有一个问题,我真的不知道如何解决它。我正在开发一个使用 Vision/VisionKit 的应用程序,每次我按下按钮运行相机以拍照和扫描文本时,都会占用内存。所以,每次我按下相机的按钮,内存总是会增加。

我的应用程序在达到 1 GB 内存时崩溃(在 9、10 次或多或少的扫描之后)。这是 Xcode 警报:

应用程序“xxx”意外退出。来自调试器的消息:由于内存问题而终止。

此外,当我拍照并且应用程序扫描该图片的文本时,我通过单击“CopyText”按钮将数据(文本)传递给另一个 ViewController,但它似乎没有释放内存或驳回之前的看法。它看起来VNDocumentCameraViewController总是在后台打开(我认为)。我从来没有遇到过这个问题,但现在它正在发生。有什么建议吗?

Ps:我很好奇,我尝试在我的 iPhone 上使用本机应用程序“Note”。经过 13-14 次扫描后,该应用程序崩溃了,它重新启动了我的设备。我要疯了。那这正常吗?

这是我的代码。我绝望了

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)
    }
      
}

标签: swiftmemorycamerafreevndocumentcameraviewcontroller

解决方案


推荐阅读