如何在按钮按下时扫描二维码?
Posted
技术标签:
【中文标题】如何在按钮按下时扫描二维码?【英文标题】:How to scan for QR codes on button press? 【发布时间】:2016-03-21 08:22:39 【问题描述】:我正在使用https://www.hackingwithswift.com/example-code/media/how-to-scan-a-qr-code 提供的代码来制作我自己的扫描应用程序。但我喜欢在按下按钮时进行扫描。现在为此,我将教程中的viewDidLoad()
部分放入它自己的函数中:
func cameraScanningLayer()
view.backgroundColor = UIColor.blackColor()
captureSession = AVCaptureSession()
let videoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
let videoInput: AVCaptureDeviceInput
do
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
catch
return
if (captureSession.canAddInput(videoInput))
captureSession.addInput(videoInput)
else
failed();
return;
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput))
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
// need to scan barcode + QRcode
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeCode39Code]
else
failed()
return
// Previewlayer with camera
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
previewLayer.frame = viewForLayer.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
viewForLayer.layer.addSublayer(previewLayer);
captureSession.startRunning();
一个按钮动作调用该函数:
func buttonScanAction()
print("Scan")
scanEnabled = true // like to use some kind of bool/switch
self.cameraScanningLayer()
我遇到的问题是:
1) 加载时相机不在视野中
2) 按下按钮后,摄像头在视野中,但始终自动扫描
所以我想到了使用全局:
var scanEnabled: Bool = false
然后,当单击按钮时,将其设置为 true 并启用扫描。
这里有一个草图供参考:
编辑 我的快速修复可能不是正确的方法。
我换了
let metadataOutput = AVCaptureMetadataOutput() ... else
failed()
return
并将其放在 if 语句之间
if (scanEnabled == true)
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput))
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
// to use them both wwe need to skip AVMetadataObjectTypeQRCode
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeCode39Code]
scanEnabled = false
else
failed()
return
【问题讨论】:
【参考方案1】:该教程的作者在这里。我的方法是使用专用的扫描视图控制器,但我猜你想将它与现有的视图控制器统一起来——这很好。两种方法都有效。
如果您想一直显示相机界面(即使不主动识别 QR 码),那么您计划使用布尔值来跟踪是否启用扫描是一个不错的选择。我的示例代码有一个被调用的foundCode()
方法,并且在找到代码时也会调用dismissViewControllerAnimated()
。
在您的版本中,您需要让foundCode()
完成停止扫描、处理解雇等所有工作。然后您可以在一个地方为您的scanEnabled
布尔值添加检查。
应该这样做:
func foundCode(code: String)
if scanCode == true
print(code)
captureSession.stopRunning()
AudioservicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
dismissViewControllerAnimated(true, completion: nil)
如果您愿意,您可以将 scanCode == true
检查上移至 didOutputMetadataObjects
以节省不必要的方法调用。
【讨论】:
tx 为您的教程。我将检查是否可以将您的代码建议(使用 foundcode 函数)用于我的“混乱”设置。我用一些似乎可以完成工作的代码编辑/更新了我的原始问题。顺便说一句:我注意到 metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode] 向数组添加类型似乎不起作用,只有第一个 ObjectType 似乎可以识别输入。就我而言,我有要扫描的二维码和条形码。【参考方案2】:感谢@alex 提出这个问题。我还使用了twostraws创建的优秀类(非常有用的Paul,非常感谢),并且还需要仅通过按钮操作来实现扫码阅读。我的解决方案如下:
我将metadataOutput
定义为全局变量,并且仅在按钮操作中我将它们集成为委托:
var metadataOutput: AVCaptureMetadataOutput!
在viewDidLoad
方法中:
metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput))
captureSession.addOutput(metadataOutput)
// Was removed this line: metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.qr]
else
failed()
return
func buttonScanAction()
print("Scan")
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
当我改变视图时,我会停止摄像头并像这样移除委托:
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)
if (captureSession?.isRunning == true)
captureSession.stopRunning()
metadataOutput.setMetadataObjectsDelegate(nil, queue: DispatchQueue.main)
【讨论】:
以上是关于如何在按钮按下时扫描二维码?的主要内容,如果未能解决你的问题,请参考以下文章