2017-12-09 39 views
1

많은 스레드와 튜토리얼을 본 적이 있지만 문제가 해결되지 않았습니다. 간단한 QR 코드 응용 프로그램을 구현하기 위해이 tutorial을 따라 갔지만 코드가 감지되지 않습니다. 대부분의 QR 관련 질문은 이전 메서드를 위임하는 것과 관련이 있습니다. 업데이트 된 대리자 메서드를 사용하고 있지만 여전히 작동하지 않는다는 것을 확인했습니다.QR 코드가 작동하지 않습니다. - 대리인 메서드가 호출되지 않습니다.

이것은 내 코드입니다. 어느 누구도 어리석은 실수를 부각시킬 수 있습니다.

import UIKit 
import AVFoundation 

class QRScannerController: UIViewController, AVCaptureMetadataOutputObjectsDelegate { 

    @IBOutlet var messageLabel:UILabel! 
    @IBOutlet var topbar: UIView! 

    var captureSession:AVCaptureSession? 
    var videoPreviewLayer:AVCaptureVideoPreviewLayer? 
    var qrCodeFrameView:UIView? 

    let supportedCodeTypes = [AVMetadataObjectTypeQRCode, 
           AVMetadataObjectTypeCode39Code, 
           AVMetadataObjectTypeUPCECode, 
           AVMetadataObjectTypeCode39Mod43Code, 
           AVMetadataObjectTypeEAN13Code, 
           AVMetadataObjectTypeEAN8Code, 
           AVMetadataObjectTypeCode93Code, 
           AVMetadataObjectTypeCode128Code, 
           AVMetadataObjectTypePDF417Code, 
           AVMetadataObjectTypeAztecCode, 
           AVMetadataObjectTypeInterleaved2of5Code, 
           AVMetadataObjectTypeITF14Code, 
           AVMetadataObjectTypeDataMatrixCode] as [String] 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Get an instance of the AVCaptureDevice class to initialize a device object and provide the video as the media type parameter. 
     let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) 
     do { 
      // Get an instance of the AVCaptureDeviceInput class using the previous device object. 
      let input = try AVCaptureDeviceInput(device: captureDevice!) 

      // Initialize the captureSession object. 
      captureSession = AVCaptureSession() 

      // Set the input device on the capture session. 
      captureSession?.addInput(input) 

      // 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 = supportedCodeTypes 

      // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer. 
      videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession!) 
      videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill 
      videoPreviewLayer?.frame = view.layer.bounds 
      view.layer.addSublayer(videoPreviewLayer!) 

      // Start video capture. 
      captureSession?.startRunning() 

      // Move the message label and top bar to the front 
      view.bringSubview(toFront: messageLabel) 
      view.bringSubview(toFront: topbar) 

      // Initialize QR Code Frame to highlight the QR code 
      qrCodeFrameView = UIView() 

      if let qrCodeFrameView = qrCodeFrameView { 
       qrCodeFrameView.layer.borderColor = UIColor.green.cgColor 
       qrCodeFrameView.layer.borderWidth = 2 
       view.addSubview(qrCodeFrameView) 
       view.bringSubview(toFront: qrCodeFrameView) 
      } 

     } catch { 
      // If any error occurs, simply print it out and don't continue any more. 
      print(error) 
      return 
     } 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 


    // MARK: - AVCaptureMetadataOutputObjectsDelegate Methods 

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

     // Check if the metadataObjects array is not nil and it contains at least one object. 
     if metadataObjects.count == 0 { 
      qrCodeFrameView?.frame = CGRect.zero 
      messageLabel.text = "No QR/barcode is detected" 
      return 
     } 

     // Get the metadata object. 
     let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject 

     if supportedCodeTypes.contains(where: { $0 == metadataObj.type }) { 
      // 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) 
      qrCodeFrameView?.frame = barCodeObject!.bounds 

      if metadataObj.stringValue != nil { 
       messageLabel.text = metadataObj.stringValue 
      } 
     } 
    } 
    } 

나는 iOS 버전 9.3.5과 아이팟에서 테스트하고 있는데 코드는 엑스 코드 8.3.2에 빠른 3입니다.

+0

더 명확하게 표시 할 수 있습니까? 실패한 부분은 어디입니까? 어떤 행동을 하시나요? 콘솔 메시지가 있습니까? 코드의 어떤 부분이 실행되고 있습니까 (중단 점이나 인쇄물로 시도 할 수 있습니까?)? – barbarity

+0

비디오가 제대로 캡쳐되고 있지만 출력 위임 메서드 "func metadataOutput (_ output : AVCaptureMetadataOutput, didOutput metadataObjects : [AVMetadataObject] from connection : AVCaptureConnection)에서 제어가 수행되지 않습니다. 바코드는 화면의 녹색 테두리로 강조 표시되지 않습니다. –

+0

위임자는 어디에서 실제로 설정합니까? 제공된 코드에서이 코드를 볼 수 없으며,이 페이지에서'delegate ='를 검색하면 아무런 결과도 얻을 수 없습니다. –

답변

2

(iOS 10.x metadataOutput)은 captureOutput입니다. 이름과 서명을 변경하면 완벽하게 작동합니다.

func captureOutput(_ output: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) { 
    // func code 
} 
+0

감사합니다. 그러나 나는 한 지점에서 정리되지 않았습니다. iOS 11 및 iOS 10 지원을 위해 두 가지 방법을 모두 추가해야합니까? 1. 'func captureOutput (_ 출력 : AVCaptureConnection!에서 출력 : AVCaptureOutput !, didOutputMetadataOutput, didOutput metadataObjects : [AVMetadataObject], 연결 : AVCaptureConnection)'2.func 캡처 출력 (_ 출력 : AVCaptureOutput !, didOutputMetadataObjects 메타 데이터 객체 : [Any] !,) ' –

+0

아니요. 시스템에서 이미 처리 한 내용이며 iOS 11 또는 iOS 10에 상관없이 의미하는 바를 이해합니다. iOS 11이 iOS 11의 작동 방식을 알 수 없기 때문에 거꾸로 돌아 가지 않습니다. 그래서, 이전 버전은 잘 작동합니다. – barbarity

+1

1+ .................................... –