iOS快速条形码读取

iOS快速条形码读取,ios,swift,barcode,Ios,Swift,Barcode,我的应用程序中正在进行条形码扫描。检测到条形码后,我停止捕获会话以允许处理条形码。但是,在处理完条形码后,我希望扫描控制器保持不动,并扫描下一个条形码。我假设启动捕获会话(startRunning())就可以了,但是图像保持冻结状态。如何再次启动捕获会话?要停止会话,请使用以下代码 self.session.stopRunning() self.session.startRunning() 要重新开始,请使用以下代码 self.session.stopRunning() self.sess

我的应用程序中正在进行条形码扫描。检测到条形码后,我停止捕获会话以允许处理条形码。但是,在处理完条形码后,我希望扫描控制器保持不动,并扫描下一个条形码。我假设启动捕获会话(startRunning())就可以了,但是图像保持冻结状态。如何再次启动捕获会话?

要停止会话,请使用以下代码

self.session.stopRunning()
self.session.startRunning()
要重新开始,请使用以下代码

self.session.stopRunning()
self.session.startRunning()
下面是实现条形码扫描仪的所有代码

import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    let session         : AVCaptureSession = AVCaptureSession()
    var previewLayer    : AVCaptureVideoPreviewLayer!
    var highlightView   : UIView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Allow the view to resize freely
        self.highlightView.autoresizingMask =   
            UIViewAutoresizing.FlexibleTopMargin |
            UIViewAutoresizing.FlexibleBottomMargin |
            UIViewAutoresizing.FlexibleLeftMargin |
            UIViewAutoresizing.FlexibleRightMargin

        // Select the color you want for the completed scan reticle
        self.highlightView.layer.borderColor = UIColor.greenColor().CGColor
        self.highlightView.layer.borderWidth = 3

        // Add it to our controller's view as a subview.
        self.view.addSubview(self.highlightView)

        // For the sake of discussion this is the camera
        let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

        // Create a nilable NSError to hand off to the next method.
        // Make sure to use the "var" keyword and not "let"
        var error : NSError? = nil

        let input : AVCaptureDeviceInput? =
            AVCaptureDeviceInput.deviceInputWithDevice(device, error: &error) 
                as? AVCaptureDeviceInput

        // If our input is not nil then add it to the session, otherwise we're kind of done!
        if input != nil {
            session.addInput(input)
        } else {
            // This is fine for a demo, do something real with this in your app. :)
            println(error)
        }

        let output = AVCaptureMetadataOutput()
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        session.addOutput(output)
        output.metadataObjectTypes = output.availableMetadataObjectTypes

        previewLayer =
            AVCaptureVideoPreviewLayer.layerWithSession(session) 
                as! AVCaptureVideoPreviewLayer
        previewLayer.frame = self.view.bounds
        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        self.view.layer.addSublayer(previewLayer)

        // Start the scanner. You'll have to end it yourself later.
        session.startRunning()
    }

    // This is called when we find a known barcode type with the camera.
    func captureOutput(
        captureOutput: AVCaptureOutput!, 
        didOutputMetadataObjects metadataObjects: [AnyObject]!,
        fromConnection connection: AVCaptureConnection!) {

        var highlightViewRect = CGRectZero
        var barCodeObject : AVMetadataObject!
        var detectionString : String!

        let barCodeTypes = [AVMetadataObjectTypeUPCECode,
            AVMetadataObjectTypeCode39Code,
            AVMetadataObjectTypeCode39Mod43Code,
            AVMetadataObjectTypeEAN13Code,
            AVMetadataObjectTypeEAN8Code,
            AVMetadataObjectTypeCode93Code,
            AVMetadataObjectTypeCode128Code,
            AVMetadataObjectTypePDF417Code,
            AVMetadataObjectTypeQRCode,
            AVMetadataObjectTypeAztecCode]

        // The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
        for metadata in metadataObjects {

            for barcodeType in barCodeTypes {

                if metadata.type == barcodeType {
                    barCodeObject = self.previewLayer.transformedMetadataObjectForMetadataObject(metadata as! AVMetadataMachineReadableCodeObject)
                    highlightViewRect = barCodeObject.bounds
                    detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue
                    self.session.stopRunning()
                    self.alert(detectionString)
                    break
                }
            }
        }

        println(detectionString)
        self.highlightView.frame = highlightViewRect
        self.view.bringSubviewToFront(self.highlightView)
    }        

    func alert(Code: String){
        let actionSheet:UIAlertController = 
            UIAlertController(
                title: "Barcode", 
                message: "\(Code)", 
                preferredStyle: UIAlertControllerStyle.Alert)

        // for alert add .Alert instead of .Action Sheet
        // start copy
        let firstAlertAction:UIAlertAction = 
            UIAlertAction(
                title: "OK",
                style: UIAlertActionStyle.Default, 
                handler: { (alertAction: UIAlertAction!) in
                // action when pressed
                self.session.startRunning()      
        })

        actionSheet.addAction(firstAlertAction)
        // end copy
        self.presentViewController(actionSheet, animated: true, completion: nil)
    }  
}

编辑了swift 2.0的上述代码:

导入UIKit
进口AVF基金会
类BarCodeViewController:UIViewController、AVCaptureMataOutputObjectsDelegate{
let session:AVCaptureSession=AVCaptureSession()
var previewLayer:AVCaptureVideoPreviewLayer!
@IBVAR highlightView:UIView!
重写func viewDidLoad(){
super.viewDidLoad()
//为完成的扫描十字线选择所需的颜色
self.highlightView.layer.borderColor=UIColor.greenColor().CGColor
self.highlightView.layer.borderWidth=3
//将其作为子视图添加到控制器的视图中。
self.view.addSubview(self.highlightView)
//为了便于讨论,这是相机
let device=AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
//创建一个可为零的NSError以切换到下一个方法。
//确保使用“var”关键字,而不是“let”
变量错误:n错误?=nil
变量输入:AVCaptureDeviceInput=AVCaptureDeviceInput()
做{
输入=尝试将AVCaptureDeviceInput(设备:设备)作为AVCaptureDeviceInput
}让我来抓你{
打印(myJSONError)
}
//如果我们的输入不是零,那么将其添加到会话中,否则我们就完成了!
如果输入!=AVCaptureDeviceInput(){
会话.添加输入(输入)
}
否则{
//这对于演示来说很好,在你的应用程序中使用它做一些真实的事情。:)
打印(错误)
}
let output=avcaptureMataOutput()
setMetadataObjectsDelegate(self,queue:dispatch\u get\u main\u queue())
session.addOutput(输出)
output.metadataObjectTypes=output.availableMetadataObjectTypes
previewLayer=AVCaptureVideoPreviewLayer(会话:会话)
previewLayer.frame=self.view.bounds
previewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill
self.view.layer.addSublayer(预览层)
//启动扫描器。你以后必须自己结束它。
会议.启动耳轴()
}
//当我们在相机中找到已知的条形码类型时,就会调用此函数。
func captureOutput(captureOutput:AVCaptureOutput!,didOutputMetadataObjects metadataObjects:[AnyObject]!,fromConnection连接:AVCaptureConnection!){
var highlightViewRect=CGRectZero
var barCodeObject:AVMetadataObject!
变量检测字符串:字符串!
让barCodeTypes=[AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeAn13Code,
AVMetadataObjectTypeAna8Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypePDF417代码,
AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeAztecCode
]
//扫描仪能够在一次扫描中捕获多个二维条形码。
用于元数据对象中的元数据{
对于barCodeTypes中的barcodeType{
如果metadata.type==barcodeType{
barCodeObject=self.previewLayer.TransformedMetadataObjectFormMetadataObject(元数据为!AVMetadataMachineReadableCodeObject)
highlightViewRect=barCodeObject.bounds
detectionString=(元数据为!avMetadataMachineAdableCodeObject)。stringValue
self.session.stopRunning()
自我警报(检测字符串)
打破
}
}
}
打印(检测字符串)
self.highlightView.frame=highlightView-rect
self.view.bringsubview到前面(self.highlightView)
}
func警报(代码:字符串){
let actionSheet:UIAlertController=UIAlertController(标题:“条形码”,消息:“\(代码)”,首选样式:UIAlertControllerStyle.Alert)
//对于警报,添加.alert而不是.Action表
//开始复制
让firstAlertAction:UIAlertAction=UIAlertAction(标题:“确定”,样式:UIAlertActionStyle.Default,处理程序:{
(alertAction:UIAlertAction!)在中
//按下时的动作
self.session.startRunning()
})
actionSheet.addAction(firstAlertAction)
//结束副本
self.presentViewController(操作表,动画:true,完成:nil)
}
}

Swift3.0版本:

import UIKit
import AVFoundation

class BarCodeViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    let session         : AVCaptureSession = AVCaptureSession()
    var previewLayer    : AVCaptureVideoPreviewLayer!
    @IBOutlet weak var highlightView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.highlightView.layer.borderColor = UIColor.green.cgColor
        self.highlightView.layer.borderWidth = 3

        // Add it to our controller's view as a subview.
        self.view.addSubview(self.highlightView)

        // For the sake of discussion this is the camera
        let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

        // Create a nilable NSError to hand off to the next method.
        // Make sure to use the "var" keyword and not "let"
        var error : NSError? = nil
        var input: AVCaptureDeviceInput = AVCaptureDeviceInput()
        do {
            input = try  AVCaptureDeviceInput(device: device) as AVCaptureDeviceInput
        } catch let myJSONError {
            print(myJSONError)
        }

        // If our input is not nil then add it to the session, otherwise we're kind of done!
        if input !=  AVCaptureDeviceInput() {
            session.addInput(input)
        }
        else {
            // This is fine for a demo, do something real with this in your app. :)
            print(error!)
        }

        let output = AVCaptureMetadataOutput()
        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        session.addOutput(output)
        output.metadataObjectTypes = output.availableMetadataObjectTypes

        previewLayer = AVCaptureVideoPreviewLayer(session: session)
        previewLayer.frame = self.view.bounds
        previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
        self.view.layer.addSublayer(previewLayer)

        // Start the scanner. You'll have to end it yourself later.
        session.startRunning()
    }

    // This is called when we find a known barcode type with the camera.
    @nonobjc func captureOutput(
        captureOutput: AVCaptureOutput!, 
        didOutputMetadataObjects metadataObjects: [AnyObject]!,
        fromConnection connection: AVCaptureConnection!) {

        var highlightViewRect = CGRect()
        var barCodeObject : AVMetadataObject!
        var detectionString : String!
        let barCodeTypes = [AVMetadataObjectTypeUPCECode,
            AVMetadataObjectTypeCode39Code,
            AVMetadataObjectTypeCode39Mod43Code,
            AVMetadataObjectTypeEAN13Code,
            AVMetadataObjectTypeEAN8Code,
            AVMetadataObjectTypeCode93Code,
            AVMetadataObjectTypeCode128Code,
            AVMetadataObjectTypePDF417Code,
            AVMetadataObjectTypeQRCode,
            AVMetadataObjectTypeAztecCode]

        // The scanner is capable of capturing multiple 2-dimensional barcodes in one scan.
        for metadata in metadataObjects {
            for barcodeType in barCodeTypes {
                if metadata.type == barcodeType {
                    barCodeObject = self.previewLayer.transformedMetadataObject(for: metadata as! AVMetadataMachineReadableCodeObject)
                    highlightViewRect = barCodeObject.bounds
                    detectionString = (metadata as! AVMetadataMachineReadableCodeObject).stringValue
                    self.session.stopRunning()
                    self.alert(Code: detectionString)
                    break
                } 
            }
        }

        print(detectionString)
        self.highlightView.frame = highlightViewRect
        self.view.bringSubview(toFront: self.highlightView)
    }

    func alert(Code: String){
        let actionSheet:UIAlertController = UIAlertController(title: "Barcode", message: "\(Code)", preferredStyle: UIAlertControllerStyle.alert)
        // for alert add .Alert instead of .Action Sheet

        // start copy
        let firstAlertAction:UIAlertAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: { (alertAction: UIAlertAction!) in
            // action when pressed              
            self.session.startRunning()
        })

        actionSheet.addAction(firstAlertAction)

        // end copy
        self.present(actionSheet, animated: true, completion: nil)
    }
}

Swift 5更新

 func captureOutput(
      captureOutput: AVCaptureOutput,
      didOutputMetadataObjects metadataObjects: [AnyObject],
      fromConnection connection: AVCaptureConnection,
      barCodeType: [AVMetadataObject.ObjectType]) -> String? {

    var detectionString: String?
    var highlightViewRect = CGRect()
    let barCodeTypes = barCodeType
    if let metadataObject = metadataObjects.first {
          for barcodeType in barCodeTypes {
              if metadataObject.type == barcodeType {
                guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return String()}
                guard let barCodeObject = self.previewLayer.transformedMetadataObject(for: readableObject) else { return String()}
                highlightViewRect = barCodeObject.bounds
                detectionString = readableObject.stringValue
               
                self.captureSession.stopRunning()
                  break
              }
          }
      }

    self.qrView.frame = highlightViewRect
    self.view.bringSubviewToFront(self.qrView)
    return detectionString
  }

如果成功了,别忘了把这个答案标记为正确的。我做了几乎相同的事情,但我交换了两行代码。我将结果字符串发送给我的处理程序,然后停止会话。它不会重新启动。如果我在将结果发送给我的处理程序之前停止了会话,那么它就工作了+