我有一个问题,我真的不知道如何解决它。我正在开发一个使用 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)
}
}