如何在 iOS 上扫描条形码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/838724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:54:25  来源:igfitidea点击:

How can I scan barcodes on iOS?

iosswiftiphonecocoa-touchbarcode

提问by Stefan

How can I simply scan barcodes on iPhone and/or iPad?

如何在 iPhone 和/或 iPad 上简单地扫描条形码?

采纳答案by Sean Owen

We produced the 'Barcodes' application for the iPhone. It can decode QR Codes. The source code is available from the zxing project; specifically, you want to take a look at the iPhone clientand the partial C++ port of the core library. The port is a little old, from circa the 0.9 release of the Java code, but should still work reasonably well.

我们为 iPhone 制作了“条形码”应用程序。它可以解码二维码。源代码可从zxing 项目获得;具体来说,你想看看iPhone客户端核心库部分C++端口。该端口有点旧,大约是 Java 代码的 0.9 版本,但应该仍然可以正常工作。

If you need to scan other formats, like 1D formats, you could continue the port of the Java code within this project to C++.

如果您需要扫描其他格式,如 1D 格式,您可以继续将此项目中的 Java 代码移植到 C++。

EDIT: Barcodes and the iphonecode in the project were retired around the start of 2014.

编辑:条形码和iphone项目中的代码在 2014 年初左右退役。

回答by Vijay

Check out ZBarreads QR Code and ECN/ISBN codes and is available as under the LGPL v2 license.

查看ZBar读取 QR 码和 ECN/ISBN 码,并且在 LGPL v2 许可下可用。

回答by Alexander

As with the release of iOS7you no longer need to use an external framework or library. The iOS ecosystem with AVFoundation now fully supports scanningalmost every code from QR over EAN to UPC.

随着发布iOS7你不再需要使用外部框架或库。带有 AVFoundation 的 iOS 生态系统现在完全支持扫描几乎所有代码,从 EAN 上的 QR 到 UPC。

Just have a look at the Tech Noteand the AVFoundation programming guide. AVMetadataObjectTypeQRCodeis your friend.

只需查看技术说明和 AVFoundation 编程指南。AVMetadataObjectTypeQRCode是你的朋友。

Here is a nice tutorialwhich shows it step by step: iPhone QR code scan library iOS7

这是一个很好的教程,一步一步地展示它: iPhone QR code scan library iOS7

Just a little example on how to set it up:

只是一个关于如何设置它的小例子:

#pragma mark -
#pragma mark AVFoundationScanSetup

- (void) setupScanner;
{
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];

    self.session = [[AVCaptureSession alloc] init];

    self.output = [[AVCaptureMetadataOutput alloc] init];
    [self.session addOutput:self.output];
    [self.session addInput:self.input];

    [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    self.output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];

    self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);

    AVCaptureConnection *con = self.preview.connection;

    con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;

    [self.view.layer insertSublayer:self.preview atIndex:0];
}

回答by Aris Bartee

The iPhone 4 camera is more than capabale of doing barcodes. The zebra crossing barcode library has a fork on github zxing-iphone. It's open-source.

iPhone 4 摄像头不仅能处理条码。斑马线条码库在 github zxing-iphone上有一个分支。它是开源的。

回答by Josh Brown

liteqris a "Lite QR Reader in Objective C ported from zxing" on github and has support for Xcode 4.

liteqr是 github 上的“从 zxing 移植的 Objective C 中的 Lite QR 阅读器”,并支持 Xcode 4。

回答by MonsieurDart

There are two major libraries:

有两个主要的库:

  • ZXinga library written in Java and then ported to Objective C / C++ (QR code only). And an other port to ObjC has been done, by TheLevelUp: ZXingObjC

  • ZBaran open source software for reading bar codes, C based.

  • ZXing一个用 Java 编写的库,然后移植到 Objective C/C++(仅限二维码)。TheLevelUp 已经完成了另一个 ObjC 的移植:ZXingObjC

  • ZBar是一种基于 C 的用于读取条码的开源软件。

According to my experiments, ZBar is far more accurate and fastthan ZXing, at least on iPhone.

根据我的实验,ZBar比 ZXing准确和快速得多,至少在 iPhone 上是这样。

回答by abdullahselek

You can find another native iOS solution using Swift 4and Xcode 9at below. Native AVFoundationframework used with in this solution.

您可以在下面找到另一个使用Swift 4Xcode 9 的原生 iOS 解决方案。AVFoundation本解决方案中使用的本机框架。

First part is the a subclass of UIViewControllerwhich have related setup and handler functions for AVCaptureSession.

第一部分是UIViewController具有相关设置和处理函数的子类AVCaptureSession

import UIKit
import AVFoundation

class BarCodeScannerViewController: UIViewController {

    let captureSession = AVCaptureSession()
    var videoPreviewLayer: AVCaptureVideoPreviewLayer!
    var initialized = false

    let barCodeTypes = [AVMetadataObject.ObjectType.upce,
                        AVMetadataObject.ObjectType.code39,
                        AVMetadataObject.ObjectType.code39Mod43,
                        AVMetadataObject.ObjectType.code93,
                        AVMetadataObject.ObjectType.code128,
                        AVMetadataObject.ObjectType.ean8,
                        AVMetadataObject.ObjectType.ean13,
                        AVMetadataObject.ObjectType.aztec,
                        AVMetadataObject.ObjectType.pdf417,
                        AVMetadataObject.ObjectType.itf14,
                        AVMetadataObject.ObjectType.dataMatrix,
                        AVMetadataObject.ObjectType.interleaved2of5,
                        AVMetadataObject.ObjectType.qr]

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setupCapture()
        // set observer for UIApplicationWillEnterForeground, so we know when to start the capture session again
        NotificationCenter.default.addObserver(self,
                                           selector: #selector(willEnterForeground),
                                           name: .UIApplicationWillEnterForeground,
                                           object: nil)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // this view is no longer topmost in the app, so we don't need a callback if we return to the app.
        NotificationCenter.default.removeObserver(self,
                                              name: .UIApplicationWillEnterForeground,
                                              object: nil)
    }

    // This is called when we return from another app to the scanner view
    @objc func willEnterForeground() {
        setupCapture()
    }

    func setupCapture() {
        var success = false
        var accessDenied = false
        var accessRequested = false

        let authorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
        if authorizationStatus == .notDetermined {
            // permission dialog not yet presented, request authorization
            accessRequested = true
            AVCaptureDevice.requestAccess(for: .video,
                                      completionHandler: { (granted:Bool) -> Void in
                                          self.setupCapture();
            })
            return
        }
        if authorizationStatus == .restricted || authorizationStatus == .denied {
            accessDenied = true
        }
        if initialized {
            success = true
        } else {
            let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera,
                                                                                        .builtInTelephotoCamera,
                                                                                        .builtInDualCamera],
                                                                          mediaType: .video,
                                                                          position: .unspecified)

            if let captureDevice = deviceDiscoverySession.devices.first {
                do {
                    let videoInput = try AVCaptureDeviceInput(device: captureDevice)
                    captureSession.addInput(videoInput)
                    success = true
                } catch {
                    NSLog("Cannot construct capture device input")
                }
            } else {
                NSLog("Cannot get capture device")
            }
        }
        if success {
            DispatchQueue.global().async {
                self.captureSession.startRunning()
                DispatchQueue.main.async {
                    let captureMetadataOutput = AVCaptureMetadataOutput()
                    self.captureSession.addOutput(captureMetadataOutput)
                    let newSerialQueue = DispatchQueue(label: "barCodeScannerQueue") // in iOS 11 you can use main queue
                    captureMetadataOutput.setMetadataObjectsDelegate(self, queue: newSerialQueue)
                    captureMetadataOutput.metadataObjectTypes = self.barCodeTypes
                    self.videoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
                    self.videoPreviewLayer.videoGravity = .resizeAspectFill
                    self.videoPreviewLayer.frame = self.view.layer.bounds
                    self.view.layer.addSublayer(self.videoPreviewLayer)
                } 
            }
            initialized = true
        } else {
            // Only show a dialog if we have not just asked the user for permission to use the camera.  Asking permission
            // sends its own dialog to th user
            if !accessRequested {
                // Generic message if we cannot figure out why we cannot establish a camera session
                var message = "Cannot access camera to scan bar codes"
                #if (arch(i386) || arch(x86_64)) && (!os(macOS))
                    message = "You are running on the simulator, which does not hae a camera device.  Try this on a real iOS device."
                #endif
                if accessDenied {
                    message = "You have denied this app permission to access to the camera.  Please go to settings and enable camera access permission to be able to scan bar codes"
                }
                let alertPrompt = UIAlertController(title: "Cannot access camera", message: message, preferredStyle: .alert)
                let confirmAction = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
                    self.navigationController?.popViewController(animated: true)
                })
                alertPrompt.addAction(confirmAction)
                self.present(alertPrompt, animated: true, completion: nil)
            }
        }
    }

    func handleCapturedOutput(metadataObjects: [AVMetadataObject]) {
        if metadataObjects.count == 0 {
            return
        }

        guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else {
            return
        }

        if barCodeTypes.contains(metadataObject.type) {
            if let metaDataString = metadataObject.stringValue {
                captureSession.stopRunning()
                displayResult(code: metaDataString)
                return
            }
        }
    }

    func displayResult(code: String) {
        let alertPrompt = UIAlertController(title: "Bar code detected", message: code, preferredStyle: .alert)
        if let url = URL(string: code) {
            let confirmAction = UIAlertAction(title: "Launch URL", style: .default, handler: { (action) -> Void in
                UIApplication.shared.open(url, options: [:], completionHandler: { (result) in
                    if result {
                        NSLog("opened url")
                    } else {
                        let alertPrompt = UIAlertController(title: "Cannot open url", message: nil, preferredStyle: .alert)
                        let confirmAction = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
                        })
                        alertPrompt.addAction(confirmAction)
                        self.present(alertPrompt, animated: true, completion: {
                            self.setupCapture()
                        })
                    }
                })        
            })
            alertPrompt.addAction(confirmAction)
        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in
            self.setupCapture()
        })
        alertPrompt.addAction(cancelAction)
        present(alertPrompt, animated: true, completion: nil)
    }

}

Second part is the extension of our UIViewControllersubclass for AVCaptureMetadataOutputObjectsDelegatewhere we catch the captured outputs.

第二部分是我们的UIViewController子类的扩展,用于AVCaptureMetadataOutputObjectsDelegate捕获捕获的输出。

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Update for Swift 4.2

Swift 4.2 更新

.UIApplicationWillEnterForegroundchanges as UIApplication.willEnterForegroundNotification.

.UIApplicationWillEnterForeground更改为UIApplication.willEnterForegroundNotification.

回答by lexx

Not sure if this will help but here is a link to an open source QR Code library. As you can see a couple of people have already used this to create apps for the iphone.

不确定这是否会有所帮助,但这里有一个指向开源QR 代码库的链接。正如您所看到的,已经有几个人使用它来为 iphone 创建应用程序。

Wikipedia has an article explaining what QR Codes are. In my opinion QR Codes are much more fit for purpose than the standard barcode where the iphone is concerned as it was designed for this type of implementation.

维基百科有一篇文章解释了什么是二维码。在我看来,QR 码比 iPhone 所关注的标准条码更适合用途,因为它是为这种类型的实现而设计的。

回答by floerkem

If support for the iPad 2 or iPod Touch is important for your application, I'd choose a barcode scanner SDK that can decode barcodes in blurry images, such as our Scandit barcode scanner SDKfor iOS and Android. Decoding blurry barcode images is also helpful on phones with autofocus cameras because the user does not have to wait for the autofocus to kick in.

如果对 iPad 2 或 iPod Touch 的支持对您的应用程序很重要,我会选择可以解码模糊图像中的条码的条码扫描器 SDK,例如适用于 iOS 和 Android 的Scandit 条码扫描器 SDK。解码模糊的条码图像在配备自动对焦摄像头的手机上也很有帮助,因为用户无需等待自动对焦启动。

Scandit comes with a free community price plan and also has a product API that makes it easy to convert barcode numbers into product names.

Scandit 附带免费的社区价格计划,还提供产品 API,可以轻松将条形码编号转换为产品名称。

(Disclaimer: I'm a co-founder of Scandit)

(免责声明:我是 Scandit 的联合创始人)