iOS:相机在第一次加载视图控制器时无法识别二维码
Posted
技术标签:
【中文标题】iOS:相机在第一次加载视图控制器时无法识别二维码【英文标题】:iOS: Camera does not recognize QR Code on first load of view controller 【发布时间】:2016-10-21 08:25:49 【问题描述】:我有一个小应用程序,它可以读取二维码进行登录,或者提供手动输入代码和登录的可能性。 该应用程序启动并直接进入登录(查看)。当我尝试扫描不起作用的二维码时 - 从未调用委托/从未引发事件。
我采用了 Larry 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);
有趣的是,一旦我使用手动输入登录并再次注销,这就会起作用,所以我再次在同一个屏幕上(可能不一样,但它的一个新实例,因为 GC 可能会破坏视图因为它已从导航堆栈中删除?)
我已将扫描仪视图作为子视图放在情节提要的 LoginView 上。对于导航,我使用 MVVMCross。 (仅供参考)
那么:我做错了什么?我需要做什么才能使其在第一次加载时工作? (我曾经这样做过 - 使用相同的代码......也许这是一个时间问题?)
【问题讨论】:
【参考方案1】:显然这是一个时间问题。 我通过添加“点击扫描”范例解决了这个问题。 点击时我执行以下代码:
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();
MetadataObjectType 设置为我们之前要查找的代码。 这解决了问题——扫描现在每次都有效。 我认为神奇的部分是 Begin- 和 CommitConfiguration 调用,因为如果我不使用触摸扫描范例,这也可以工作。
【讨论】:
以上是关于iOS:相机在第一次加载视图控制器时无法识别二维码的主要内容,如果未能解决你的问题,请参考以下文章
我的简单相机应用程序(android)在第一次尝试后不会加载相机视图