应用程序在模拟器中运行良好,但在 phone 上无法正常运行

App works fine in simulator but doesn't function correctly on phone

我正在 Swift 中为 iOS 创建一个 OCR 应用程序,它需要按下一个按钮 ('snap/upload image'),然后允许用户从他们的照片中选择图像或拍照。这在 iPhone 11 pro max 模拟器中完美运行,但是,当 运行ning 在 iPhone 8 模拟器和 iPhone 8 本身上时,我收到错误消息或它只是行不通。我附上了代码和错误。

import UIKit
import MobileCoreServices
import TesseractOCR
import GPUImage

class ViewController: UIViewController {
  @IBOutlet weak var textView: UITextView!
  @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

  override func viewDidLoad() {
    super.viewDidLoad()
  }

  // IBAction methods
  @IBAction func backgroundTapped(_ sender: Any) {
    view.endEditing(true)
  }

  @IBAction func takePhoto(_ sender: Any) {
    let imagePickerActionSheet =
      UIAlertController(title: "Snap/Upload Image",
                        message: nil,
                        preferredStyle: .actionSheet)

    if UIImagePickerController.isSourceTypeAvailable(.camera) {
      let cameraButton = UIAlertAction(
        title: "Take Photo",
        style: .default) { (alert) -> Void in
          self.activityIndicator.startAnimating()
          let imagePicker = UIImagePickerController()
          imagePicker.delegate = self
          imagePicker.sourceType = .camera
          imagePicker.mediaTypes = [kUTTypeImage as String]
          self.present(imagePicker, animated: true, completion: {
            self.activityIndicator.stopAnimating()
          })
      }
      imagePickerActionSheet.addAction(cameraButton)
    }

    let libraryButton = UIAlertAction(
      title: "Choose Existing",
      style: .default) { (alert) -> Void in
        self.activityIndicator.startAnimating()
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .photoLibrary
        imagePicker.mediaTypes = [kUTTypeImage as String]
        self.present(imagePicker, animated: true, completion: {
          self.activityIndicator.stopAnimating()
        })
    }
    imagePickerActionSheet.addAction(libraryButton)

    let cancelButton = UIAlertAction(title: "Cancel", style: .cancel)
    imagePickerActionSheet.addAction(cancelButton)

    present(imagePickerActionSheet, animated: true)
  }

  // Tesseract Image Recognition
  func performImageRecognition(_ image: UIImage) {
    let scaledImage = image.scaledImage(1000) ?? image
    let preprocessedImage = scaledImage.preprocessedImage() ?? scaledImage

    if let tesseract = G8Tesseract(language: "eng+fra") {
      tesseract.engineMode = .tesseractCubeCombined
      tesseract.pageSegmentationMode = .auto

      tesseract.image = preprocessedImage
      tesseract.recognize()
      textView.text = tesseract.recognizedText
    }
    activityIndicator.stopAnimating()
  }
}

// MARK: - UINavigationControllerDelegate
extension ViewController: UINavigationControllerDelegate {
}

// MARK: - UIImagePickerControllerDelegate
extension ViewController: UIImagePickerControllerDelegate {
  func imagePickerController(_ picker: UIImagePickerController,
       didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    guard let selectedPhoto =
      info[.originalImage] as? UIImage else {
        dismiss(animated: true)
        return
    }
    activityIndicator.startAnimating()
    dismiss(animated: true) {
      self.performImageRecognition(selectedPhoto)
    }
  }
}

// MARK: - UIImage extension
extension UIImage {
  func scaledImage(_ maxDimension: CGFloat) -> UIImage? {
    var scaledSize = CGSize(width: maxDimension, height: maxDimension)

    if size.width > size.height {
      scaledSize.height = size.height / size.width * scaledSize.width
    } else {
      scaledSize.width = size.width / size.height * scaledSize.height
    }

    UIGraphicsBeginImageContext(scaledSize)
    draw(in: CGRect(origin: .zero, size: scaledSize))
    let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return scaledImage
  }

  func preprocessedImage() -> UIImage? {
    let stillImageFilter = GPUImageAdaptiveThresholdFilter()
    stillImageFilter.blurRadiusInPixels = 15.0
    let filteredImage = stillImageFilter.image(byFilteringImage: self)
    return filteredImage
  }
}

[显示 'snap/upload image' 的位置及其限制条件][1]

当应用程序在 iphone 11 max pro 模拟器上运行 运行 时,它可以工作,但是在 iphone 8 模拟器上,这是我拥有的设备,它会出现此错误

[错误][2]

在控制台中:

2019-10-28 17:51:50.440498+0000 Love In A Snap[14813:703702] -[Love_In_A_Snap.ViewController takePhoto:]: unrecognized selector sent to instance 0x7fe503d06d50
2019-10-28 17:51:50.454363+0000 Love In A Snap[14813:703702] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Love_In_A_Snap.ViewController takePhoto:]: unrecognized selector sent to instance 0x7fe503d06d50'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010e63d1ee __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x000000010c275b20 objc_exception_throw + 48
    2   CoreFoundation                      0x000000010e65e154 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    3   UIKitCore                           0x0000000119832e79 -[UIResponder doesNotRecognizeSelector:] + 302
    4   CoreFoundation                      0x000000010e641f6c ___forwarding___ + 1436
    5   CoreFoundation                      0x000000010e6440f8 _CF_forwarding_prep_0 + 120
    6   UIKitCore                           0x0000000119806082 -[UIApplication sendAction:to:from:forEvent:] + 83
    7   UIKitCore                           0x00000001191ec8e5 -[UIControl sendAction:to:forEvent:] + 223
    8   UIKitCore                           0x00000001191ecc2f -[UIControl _sendActionsForEvents:withEvent:] + 398
    9   UIKitCore                           0x00000001191ebb8e -[UIControl touchesEnded:withEvent:] + 481
    10  UIKitCore                           0x0000000119840a31 -[UIWindow _sendTouchesForEvent:] + 2604
    11  UIKitCore                           0x0000000119842338 -[UIWindow sendEvent:] + 4596
    12  UIKitCore                           0x000000011981d693 -[UIApplication sendEvent:] + 356
    13  UIKitCore                           0x000000011989de5a __dispatchPreprocessedEventFromEventQueue + 6847
    14  UIKitCore                           0x00000001198a0920 __handleEventQueueInternal + 5980
    15  CoreFoundation                      0x000000010e5a0271 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    16  CoreFoundation                      0x000000010e5a019c __CFRunLoopDoSource0 + 76
    17  CoreFoundation                      0x000000010e59f974 __CFRunLoopDoSources0 + 180
    18  CoreFoundation                      0x000000010e59a67f __CFRunLoopRun + 1263
    19  CoreFoundation                      0x000000010e599e66 CFRunLoopRunSpecific + 438
    20  GraphicsServices                    0x000000011055dbb0 GSEventRunModal + 65
    21  UIKitCore                           0x0000000119804dd0 UIApplicationMain + 1621
    22  Love In A Snap                      0x000000010a61132b main + 75
    23  libdyld.dylib                       0x000000010d132d29 start + 1
    24  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

[给未来读者的总结:]

结果是 unrecognized selector 崩溃;由于 OP 未能提及崩溃或崩溃日志(OP 仅使用 "nothing happens" 或 "can't press the button" 等短语,诊断变得更加困难。但我们最终还是做到了。

但是有点不寻常unrecognized selector,因为Cocoa不认识的选择器是[Love_In_A_Snap.ViewController takePhoto:],我们可以很清楚 ViewController 有那个方法:

 @IBAction func takePhoto(_ sender: Any) {

最后我们不得不通过假设事情不知何故变成 "stale" 来解决这个问题。我们删除了故事板中的连接并重新创建它。那种固定的东西,但不是在所有情况下。然后我们从设备中删除了该应用程序并清理了 DerivedData 文件夹,并修复了它。