2016-10-21 5 views
1

로그인을 위해 QR 코드를 읽거나 코드를 직접 입력하고 로그인 할 수있는 작은 앱이 있습니다. 앱이 시작되고 로그인 (보기)으로 바로 향합니다. 작동하지 않는 qr 코드를 검색하려고하면 대리자가 절대로 호출되지 않거나 이벤트가 발생하지 않습니다. iOS : 카메라가 처음으로보기 컨트롤러를로드 할 때 QR 코드를 인식하지 못합니다.

나는 래리 OBrien http://www.knowing.net/index.php/2013/10/09/natively-recognize-barcodesqr-codes-in-ios-7-with-xamarin-ios/

의 접근 방식을 채택 그리고 사용하기 위해 내 자신의 ScannerView 클래스를 생성 :

public sealed partial class ScannerView : UIView 
{ 
    private readonly AVCaptureVideoPreviewLayer _layer; 
    public AVCaptureSession Session { get; } 
    private readonly AVCaptureMetadataOutput _metadataOutput; 

    public event EventHandler<AVMetadataMachineReadableCodeObject> MetadataFound = delegate { }; 
    public ScannerView (IntPtr handle) : base (handle) 
    { 
     Session = new AVCaptureSession(); 
     var camera = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video); 
     var input = AVCaptureDeviceInput.FromDevice(camera); 
     Session.AddInput(input); 

     //Add the metadata output channel 
     _metadataOutput = new AVCaptureMetadataOutput {RectOfInterest = Bounds}; 
     var metadataDelegate = new MetadataOutputDelegate(); 
     var dispatchQueue = new DispatchQueue("scannerQueue"); 
     _metadataOutput.SetDelegate(metadataDelegate, dispatchQueue); 
     Session.AddOutput(_metadataOutput); 

     _layer = new AVCaptureVideoPreviewLayer(Session) 
     { 
      MasksToBounds = true, 
      VideoGravity = AVLayerVideoGravity.ResizeAspectFill, 
      Frame = Bounds 
     }; 

     Layer.AddSublayer(_layer); 

     // Hand event over to subscriber 
     metadataDelegate.MetadataFound += (s, e) => MetadataFound(s, e); 
    } 

    public override void LayoutSubviews() 
    { 
     base.LayoutSubviews(); 
     _layer.Frame = Bounds; 
     _metadataOutput.RectOfInterest = Bounds; 
    } 

    public void SetMetadataType(AVMetadataObjectType type) 
    { 
     //Confusing! *After* adding to session, tell output what to recognize... 
     _metadataOutput.MetadataObjectTypes = type; 
    } 
} 

그리고 내 LoginView에서 나는 다음을 수행하십시오

public override void ViewWillAppear(bool animated) 
    { 
     base.ViewWillAppear(animated); 
     // Manipulate navigation stack 
     NavigationController.SetViewControllers(
      NavigationController.ViewControllers.Where(
       viewController => viewController is LoginView).ToArray(), false); 

     ScannerView.MetadataFound += (s, e) => 
     { 
      Console.WriteLine($"Found: [{e.Type.ToString()}] {e.StringValue}"); 
      LoginViewModel.BarCode = e.StringValue; 
      if (LoginViewModel.DoneCommand.CanExecute()) 
      { 
       ScannerView.Session.StopRunning(); 
       LoginViewModel.DoneCommand.Execute(); 
      } 
     }; 
    } 

    public override void ViewDidAppear(bool animated) 
    { 
     base.ViewDidAppear(animated); 
     ScannerView.Session.StartRunning(); 
     ScannerView.SetMetadataType(AVMetadataObjectType.QRCode | AVMetadataObjectType.EAN13Code); 
    } 

재미 문제는, 수동 입력으로 로그인하고 다시 로그 아웃하면 이것이 작동한다는 것입니다. 그래서 저는 같은 화면에서 다시 볼 수 있습니다 (아마도 똑같지는 않지만 새로운 inst GC가 탐색 스택에서 제거되면보기가 파괴 될 수 있습니다.)

나는 storyview의 LoginView에서 scannerview를 하위보기로 지정했습니다. 탐색을 위해 MVVMCross를 사용합니다. (정보 만)

So : 내가 뭘 잘못하고 있니? 첫 번째로드에서 작동하게하려면 어떻게해야합니까? (같은 코드로 한 번 해보 겠지만 타이밍상의 문제 일 수도 있습니다.)

답변

0

분명히 타이밍 문제입니다. "탭하여 스캔"패러다임을 추가하여 문제를 해결했습니다. 나는 다음과 같은 코드를 실행 태핑 경우 : MetadataObjectType이 코드로 설정

 public override void TouchesBegan(NSSet touches, UIEvent evt) 
    { 
     base.TouchesBegan(touches, evt); 
     Console.WriteLine($"Current types to scan: {this.MetadataOutput.MetadataObjectTypes}"); 
     this.SetMetadataType(this.MetadataObjectType); 
     Console.WriteLine($"New types to scan: {this.MetadataOutput.MetadataObjectTypes}"); 
    } 

    public void SetMetadataType(AVMetadataObjectType type) 
    { 
     //Confusing! *After* adding to session, tell output what to recognize... 
     this.Session.BeginConfiguration(); 
     this.MetadataOutput.MetadataObjectTypes = type; 
     this.Session.CommitConfiguration(); 
    } 

는 우리가 전에 찾고 있습니다. 그게 문제를 해결합니다. 이제 스캐닝이 매번 작동합니다. 패러다임을 스캔하기 위해 터치를 사용하지 않으면 마술 부분이 Begin- 및 CommitConfiguration 호출이라고 생각합니다.