Приложение Swift: "VNDocumentCameraViewController" Как освободить память, отключив ViewController?
У меня проблема, и я действительно не знаю, как ее решить. Я разрабатываю приложение, которое использует Vision/VisionKit, и каждый раз, когда я нажимаю кнопку, чтобы запустить камеру, чтобы сделать снимок и отсканировать текст, требуется память. Итак, каждый раз, когда я нажимаю кнопку камеры, память всегда будет увеличиваться.
Мое приложение вылетает, когда достигает 1 ГБ памяти (после 9, 10 сканирований более или менее). Это предупреждение Xcode:
Приложение "xxx" неожиданно закрылось. Сообщение от отладчика: Прервано из-за проблемы с памятью.
Кроме того, когда я делаю снимок, и приложение сканирует текст этого рисунка, я передаю данные (текст) другому ViewController, нажимая кнопку "CopyText", но кажется, что это не освобождает память или отклонить предыдущее мнение. Это выглядит как
VNDocumentCameraViewController
всегда открыт в фоновом режиме (я думаю). Я никогда не сталкивался с этой проблемой, но теперь это происходит. Любое предложение?
Ps: Мне было любопытно, и я попробовал использовать родное приложение "Note" на своем iPhone. После 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)
}
}