因此,我剛剛接管了一個iOS項目作爲他們的第一個內部開發者,之前這個應用程序是由一個機構開發的。QR碼掃描不起作用
該應用程序的功能之一是,它需要掃描QR碼 - 通過前面的開發人員遵循的代碼的外觀this教程AppCoda實施QR掃描。一切看起來都很好,我看不出代碼有什麼問題,但它不起作用。
我還下載了完成的教程項目,並且在我嘗試QR掃描時工作。我也嘗試複製和粘貼每一行,以便它與工作教程相同但沒有運氣。
我把我的頭髮撕了出來,試圖找出它爲什麼不工作。
任何幫助非常感謝!
enum ScanState : Int {
case newDevice = 1
case resetDevice = 2
case replaceDevice = 3
}
class QRScannerViewController: BaseViewController,AVCaptureMetadataOutputObjectsDelegate {
@IBOutlet var scanZoneView: UIView!
@IBOutlet var scannerVIew: UIView!
@IBOutlet var scanInfoLabel: UILabel!
var capturedQR: String? = nil
var captureSession:AVCaptureSession?
var videoPreviewLayer:AVCaptureVideoPreviewLayer?
var qrCodeFrameView:UIView?
let supportedBarCodes = [AVMetadataObject.ObjectType.qr, AVMetadataObject.ObjectType.code128, AVMetadataObject.ObjectType.code39, AVMetadataObject.ObjectType.code93, AVMetadataObject.ObjectType.upce, AVMetadataObject.ObjectType.pdf417, AVMetadataObject.ObjectType.ean13, AVMetadataObject.ObjectType.aztec]
var type = "leg scan"
var device:Device?
var state:ScanState = .newDevice
override func viewDidLoad() {
super.viewDidLoad()
scanInfoLabel.text = "Scan your existing\nleg QR code"
self.navigationController?.navigationBar.dark()
//self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
#if NOHARDWARE
moveToNextViewController()
#else
initiateCapture()
#endif
}
func initiateCapture() {
let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
var error:NSError?
let input: AnyObject!
do {
input = try AVCaptureDeviceInput(device: captureDevice!) as AVCaptureDeviceInput
} catch let error1 as NSError {
error = error1
input = nil
} catch _ {
input = nil
}
if (error != nil) {
// If any error occurs, simply log the description of it and don't continue any more.
print("\(error?.localizedDescription)")
return
}
// Initialize the captureSession object.
captureSession = AVCaptureSession()
// Set the input device on the capture session.
captureSession?.addInput(input as! AVCaptureInput)
// Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession?.addOutput(captureMetadataOutput)
// Set delegate and use the default dispatch queue to execute the call back
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = supportedBarCodes
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!)
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.frame = scannerVIew.layer.bounds
scannerVIew.layer.addSublayer(videoPreviewLayer!)
// Start video capture.
captureSession?.startRunning()
// Initialize QR Code Frame to highlight the QR code
qrCodeFrameView = UIView()
qrCodeFrameView?.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView?.layer.borderWidth = 2
scannerVIew.addSubview(qrCodeFrameView!)
scannerVIew.bringSubview(toFront: qrCodeFrameView!)
//qrCapturedLabel.text = "No QR code is detected"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func metadataOutput(captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects == nil || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
return
}
// Get the metadata object.
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
// Here we use filter method to check if the type of metadataObj is supported
// Instead of hardcoding the AVMetadataObjectTypeQRCode, we check if the type
// can be found in the array of supported bar codes.
if supportedBarCodes.filter({ $0 == metadataObj.type }).count > 0 {
// If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj as AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject
let intersectionRect = barCodeObject.bounds.intersection(self.scanZoneView.frame)
if !intersectionRect.isNull &&
(intersectionRect.size.width * intersectionRect.size.height) > self.scanZoneView.bounds.width * self.scanZoneView.bounds.height/7 {
qrCodeFrameView?.frame = barCodeObject.bounds
if process(metadataObj.stringValue!) {
captureSession?.stopRunning()
}
}
}
}
@IBAction func didTapCancel(_ sender: AnyObject) {
self.dismiss(animated: true, completion: nil)
}
}
extension QRScannerViewController {
func process(_ scanText : String) -> Bool {
var legCode : String
let codeComponents = scanText.components(separatedBy: ";")
if codeComponents.count > 0 {
legCode = codeComponents[0]
} else {
// Invalid number of parameters seperated by a ;
return false
}
// TODO Validate the LEG to LEG-XXXXX
if legCode.hasPrefix("LEG-") {
let delta: Int64 = 1 * Int64(NSEC_PER_SEC)
let time = DispatchTime.now() + Double(delta)/Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: time, execute: {
switch self.state {
case .resetDevice:
let realm = try! Realm()
let deviceList = realm.objects(Device.self)
let lc = legCode
self.device = deviceList.filter("legCode = %@", lc).first
if self.device == nil {
// TODO Error message: Device not associated with LEG
let vc = ErrorViewController.createErrorViewController(.DeviceNotFound)
self.present(vc, animated: true, completion: nil)
return
}
self.moveToNextViewController()
default:
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
});
return true
}
return false
}
func moveToNextViewController() {
let inspectionStoryboard = UIStoryboard(name: "Impact", bundle: nil)
if let resetVC = inspectionStoryboard.instantiateViewController(withIdentifier: ImpactDetectionViewController.storyboardID) as? ImpactDetectionViewController {
resetVC.device = device
// TODO Pass the impact type across too when the G2 API is set
self.navigationController?.pushViewController(resetVC, animated: false)
}
}
@IBAction func cancelToVC(_ segue: UIStoryboardSegue) { }
}
編輯
如果不工作,我的意思是永遠不會被調用爲AVCaptureMetadataOutputObjectsDelegate
委託所以它似乎從來沒有被檢測QR碼。在AppCoda教程中,它覆蓋了一個綠色方塊,它檢測到QR碼,但是當我將該代碼放入此應用程序時,這種情況從未發生過。
相機實際上正在運行,但QR碼從未被檢測到。
我覺得也沒關係共享庫,如果我上傳它作爲一個評論,我一直在使用這種吊艙,方便生活,只是想要建議:https://github.com/yannickl/QRCodeReader.swift – Glenn
感謝Glenn,我確實研究過這個,但是當我安裝了pod時,有11個錯誤來自框架,所以我決定只是更容易得到這個實現工作 –
你能給我們更多的細節嗎?當你運行這段代碼時會發生什麼?相機是否在運行?你能看到相機視圖框?您是否嘗試在'didOutput metadataObject'處檢查斷點? – Bluewings