2017-10-05 6 views
0

그래서 저는 이전에이 앱이 대행사에 의해 개발 된 최초의 사내 개발자로서 iOS 프로젝트를 인수했습니다.QR 코드 스캐닝이 작동하지 않습니다.

응용 프로그램의 기능 중 하나는 이전 개발자가 QR 스캔을 구현하는 AppCoda의 this 튜토리얼을 따라 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) { } 

} 

나는 그것이 결코 QR 코드를 탐지 할 것 같다, 그래서 AVCaptureMetadataOutputObjectsDelegate에 대한 대리자가 호출되고 있지 않습니다 의미 작동하지으로 편집

. AppCoda 튜토리얼에서는 QR 코드를 감지하는 녹색 사각형을 겹쳐 씁니다. 그러나이 코드를이 앱에 넣으면 결코 발생하지 않습니다.

카메라는 실제로 작동하지만 QR 코드는 절대로 검색되지 않습니다.

+1

func metadataOutput(captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { 

을 변경 하였다 https://github.com/yannickl/QRCodeReader.swift – Glenn

+0

감사합니다. Glenn, 그 부분을 살펴 봤지만 프레임을 설치할 때 프레임에서 오는 11 개의 오류가 있었기 때문에 포드를 설치하는 것이 더 쉬울 것이라고 결정했습니다. 이 구현 작업 –

+0

좀 더 자세한 정보를 제공 할 수 있습니까? 이 코드를 실행하면 어떻게됩니까? 카메라가 작동합니까? 카메라 뷰 프레임을 볼 수 있습니까? 'didOutput metadataObject'에서 중단 점을 확인하려고 했습니까? – Bluewings

답변

5

대답은 간단 믿을 수 있었다 (그리고 성가 시게) 밝혀! 물론 Swift 4에서는 대표자가 약간 변경되었습니다. 내가 가진 모든 문제를 해결하려면 그냥 내가 쉽게 생활이 포드를 사용하고, 내가 주석으로 게시 경우가 라이브러리를 공유 할 수 괜찮아 생각

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { 
+0

감사합니다. 당신은 저에게 많은 시간을 절약 해주었습니다 : D –

+0

답장을 보내 주셔서 감사합니다! – Hamsternik

-1

AVCaptureMetadataOutput의 대표단에 수업을 연결하지 않아서 AVCaptureMetadataOutputObjectsDelegate 함수가 호출되지 않습니다. 더 많은 정보 : https://developer.apple.com/documentation/avfoundation/avcapturemetadataoutputobjectsdelegate

이 시도 :

// Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session. 
    let captureMetadataOutput = AVCaptureMetadataOutput() 
    captureMetadataOutput.metadataObjectsDelegate = self // assign self to the delegate. 
    captureSession?.addOutput(captureMetadataOutput) 
+0

답변 해 주셔서 감사합니다. 약간의 진전이있는 것 같습니다. 필자는 코드 줄을 돌아 다니며'captureMetadataOutput.metadataObjectTypes'에 지원되지 않는 유형을 전달하고 대신'availableMetadataObjectTypes'를 사용한다고 치명적인 오류가 발생했습니다. 나는 그것을했지만 지금은'metadataObjectTypes' 배열이 비어 있습니다. –