¿Cómo puedo escanear códigos de barras en iOS?

189

¿Cómo puedo simplemente escanear códigos de barras en iPhone y / o iPad?

Stefan
fuente
77
Lamentablemente, la cámara del iPhone es actualmente terrible para leer códigos de barras, ya que su lente tiene un enfoque fijo en ∞. Sin embargo, la mejor de las suertes!
Alastair Stuart
1
Solo he estado resolviendo este problema, así que escribiré mis observaciones. Probé pocas opciones. RSBarcodes_Swift - fue fácil de integrar, pero tuvo un rendimiento muy pobre. ZBarSDK: también fue fácil de implementar, aunque busqué en Google para encontrar cómo. Pero tuvo un rendimiento realmente bueno (no escaneó datamatrix y otros códigos raros) funciona muy bien para códigos de barras / QRCode. Pero Scandit fue el mejor de todos. Súper rápido, escanea todo. Lamentablemente cuesta bastante.
Katafalkas

Respuestas:

82

Producimos la aplicación 'Códigos de barras' para iPhone. Puede decodificar códigos QR. El código fuente está disponible desde el proyecto zxing ; específicamente, desea echar un vistazo al cliente de iPhone y al puerto parcial C ++ de la biblioteca principal . El puerto es un poco viejo, de alrededor de la versión 0.9 del código Java, pero aún debería funcionar razonablemente bien.

Si necesita escanear otros formatos, como los formatos 1D, puede continuar el puerto del código Java dentro de este proyecto a C ++.

EDITAR: los códigos de barras y el iphonecódigo en el proyecto se retiraron a principios de 2014.

Sean Owen
fuente
Sean, ¿qué tipo de licencia utiliza? Quiero crear una aplicación paga que use Zbar. ¿Es eso posible bajo el acuerdo de licencia?
Radu
1
Para ser claros, en este momento, ¿ZXing en el iPhone solo admite códigos QR?
RefuX
Creo que se ha portado más a C ++, pero desafortunadamente el puerto sigue siendo un eco aproximado y desactualizado del código Java. Entonces, sí más es compatible, aunque tal vez no sea así.
Sean Owen
ZXing para iPhone todavía tiene pérdidas de memoria en 1.7 ver.
Yoon Lee
Por la lista de problemas en git of zXing, entiendo que solo podemos escanear el código de barras en modo horizontal.
Sagrian
81

Echa un vistazo a ZBar lee el código QR y los códigos ECN / ISBN y está disponible bajo la licencia LGPL v2.

Vijay
fuente
55
Parcialmente correcto. ZBar.app tiene licencia de Apache License (Versión 2.0), sin embargo, la biblioteca tiene licencia de LGPL v2.
Sean
3
Lamentablemente, la licencia requiere que comparta los archivos de objetos de su aplicación con cualquiera que los solicite ... consulte zbar.sourceforge.net/iphone/sdkdoc/licensing.html
Ben Clayton
1
@BenClayton, ¿qué significa compartir los archivos de objetos de la aplicación?
Dejell
@Odelya Enviando los archivos .o generados por Xcode a cualquier persona, teóricamente permitiéndoles construir su aplicación. Definitivamente no estoy contento de hacer esto (especialmente para mis clientes), así que ZBar está fuera de discusión para nosotros. La página de licencias de ZBar sugiere que 'esperemos que nadie las solicite'.
Ben Clayton
@BenClayton A. Gracias B. Podría cambiar el componente si alguien pregunta y requiere que los usuarios de la aplicación ya descargados descarguen una versión más nueva. ¿Es suficiente? C. Entonces, ¿qué biblioteca estás usando?
Dejell
56

Al igual que con el lanzamiento de iOS7usted, ya no necesita usar un marco externo o biblioteca. El ecosistema iOS con AVFoundation ahora es totalmente compatible con el escaneo de casi todos los códigos desde QR a través de EAN a UPC.

Solo eche un vistazo a la Nota técnica y la guía de programación AVFoundation. AVMetadataObjectTypeQRCodees tu amigo.

Aquí hay un buen tutorial que lo muestra paso a paso: biblioteca de escaneo de códigos QR de iPhone iOS7

Solo un pequeño ejemplo sobre cómo configurarlo:

#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];
}
Alejandro
fuente
1
Si desea detectar el código de barras de la imagen en iOS8, este tutorial puede ser útil.
NSDeveloper
Descubrí que tenía que llamar startRunninga la sesión para que el código anterior funcionara en caso de que ayude a alguien :)
Chris
13

La cámara del iPhone 4 es más que capaz de hacer códigos de barras. La biblioteca de códigos de barras del paso de cebra tiene una bifurcación en github zxing-iphone . Es de código abierto.

Aris Bartee
fuente
1
¿Su publicación parece implicar que este puerto de ZXing puede escanear más que solo QRCodes? ¿Es ese el caso?
RefuX
44
El tenedor de github parece estar muerto, como lo indica este número: github.com/joelind/zxing-iphone/issues/3
Josh Brown
10

liteqr es un "Lector QR QR Lite en Objective C portado desde zxing" en github y tiene soporte para Xcode 4.

Josh Brown
fuente
10

Hay dos bibliotecas principales:

  • ZXing una biblioteca escrita en Java y luego portada a Objective C / C ++ (solo código QR). Y TheLevelUp ha hecho otro puerto a ObjC: ZXingObjC

  • ZBar, un software de código abierto para leer códigos de barras, basado en C.

Según mis experimentos, ZBar es mucho más preciso y rápido que ZXing, al menos en iPhone.

MonsieurDart
fuente
Me parece que ZXingObjC es el que debería ser llevado a la cima con más votos por ahora. Yo no lo he utilizado todavía , pero la descripción dice que está en paridad con ZXing 2.0.
Shaolo
La licencia de ZBar requiere que ofrezca los archivos de objetos a los usuarios, para que puedan ejecutarlos y modificar su biblioteca también.
Dejell
Recomiendo ZXingObjC
Dejell
7

Puede encontrar otra solución iOS nativa usando Swift 4 y Xcode 9 a continuación. AVFoundationMarco nativo utilizado con en esta solución.

La primera parte es una subclase para la UIViewControllerque se han relacionado funciones de configuración y manejo 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)
    }

}

La segunda parte es la extensión de nuestra UIViewControllersubclase para AVCaptureMetadataOutputObjectsDelegatecapturar los resultados capturados.

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Actualización para Swift 4.2

.UIApplicationWillEnterForegroundcambia como UIApplication.willEnterForegroundNotification.

abdullahselek
fuente
¿esto dará el nombre del producto, tamaño, precio, url del producto, moneda, nombre de la tienda? o solo dará el número del código de barras @abdullahselek
R. Mohan
@ R. Mohan está relacionado con el código de barras que lees. Verifique AVCaptureMetadataOutput y AVMetadataMachineReadableCodeObject e intente leer metadataObjectsdentro de la función handleCapturedOutput .
abdullahselek
Ok, lo intentaré. Gracias por la respuesta @abdullahselek
R. Mohan
5

No estoy seguro de si esto ayudará, pero aquí hay un enlace a una biblioteca de código QR de código abierto . Como puede ver, un par de personas ya lo han usado para crear aplicaciones para el iPhone.

Wikipedia tiene un artículo que explica qué son los códigos QR . En mi opinión, los códigos QR son mucho más adecuados para el propósito que el código de barras estándar en lo que respecta al iPhone, ya que fue diseñado para este tipo de implementación.

lexx
fuente
5

Si el soporte para iPad 2 o iPod Touch es importante para su aplicación, elegiría un SDK de escáner de código de barras que pueda decodificar códigos de barras en imágenes borrosas, como nuestro SDK de escáner de código de barras Scandit para iOS y Android. Decodificar imágenes borrosas de códigos de barras también es útil en teléfonos con cámaras de enfoque automático porque el usuario no tiene que esperar a que se active el enfoque automático.

Scandit viene con un plan de precio comunitario gratuito y también tiene una API de producto que facilita la conversión de números de códigos de barras en nombres de productos.

(Descargo de responsabilidad: soy cofundador de Scandit)

floerkem
fuente
4

Si todavía está disponible, puede echar un vistazo al código fuente del lector de datos DataMatrix de Stefan Hafeneger ( proyecto de código de Google ; publicación archivada del blog ).

Galés
fuente
¿Cómo es tu experiencia con esta aplicación? ¡Para mí se necesitan 10 segundos o más para decodificar un código de barras simple de matriz de datos!
iamj4de
1
El enlace se cambia a stefan.hafeneger.name/blog/2009/09/08/…
Suresh Varma
1
Enlace directo (no creo que Google vaya a desaparecer esto por un tiempo) code.google.com/p/barcodeapp
¿Alguien sabe cuál es el nombre oficial de la aplicación de Stefan en la tienda de aplicaciones? Me gustaría descargarlo antes de sumergirme en el código real.
macutan
3

El problema con la cámara del iPhone es que los primeros modelos (de los cuales hay toneladas en uso) tienen una cámara de enfoque fijo que no puede tomar fotos enfocadas para distancias de menos de 2 pies. Las imágenes son borrosas y distorsionadas y si se toman desde una distancia mayor no hay suficiente detalle / información del código de barras.

Algunas compañías han desarrollado aplicaciones para iPhone que pueden adaptarse a eso mediante el uso de tecnologías avanzadas de desenfoque. Esas aplicaciones que puedes encontrar en la tienda de aplicaciones de Apple: pic2shop, RedLaser y ShopSavvy. Todas las compañías han anunciado que también tienen SDK disponibles, algunos de forma gratuita o con condiciones muy preferenciales, échale un vistazo.

Nas Banov
fuente
Intenté usar ShopSavvy con un iPhone 3G. Es divertido, pero se bloquea con mucha frecuencia y le cuesta mucho leer códigos de barras planos y muy claros.
James Moore el
1
Y acabo de probar pic2shop. Cita de mi prometida: "se supone que esto facilitará nuestras vidas ¿CÓMO?" Es una aplicación linda, pero no puedo leer un código de barras por lo que puedo decir.
James Moore
¿Qué formato intentaste leer? Intenté usar pic2shop para escanear EAN y funciona muy bien. Sin embargo, la tarifa de la licencia es costosa, incluso más que RedLaser.
iamj4de
2

¡Con Swift 5 es simple y súper rápido!

Solo necesita agregar vainas de cacao "BarcodeScanner" aquí está el código completo

source 'https://github.com/CocoaPods/Specs.git' 
platform :ios, '12.0' 
target 'Simple BarcodeScanner' 
do   
pod 'BarcodeScanner' 
end

Asegúrese de agregar permiso de cámara en su archivo .plist

<key>NSCameraUsageDescription</key>
<string>Camera usage description</string>

Y agregue Scanner y maneje el resultado en su ViewController de esta manera

import UIKit
import BarcodeScanner

class ViewController: UIViewController, BarcodeScannerCodeDelegate, BarcodeScannerErrorDelegate, BarcodeScannerDismissalDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        let viewController = BarcodeScannerViewController()
        viewController.codeDelegate = self
        viewController.errorDelegate = self
        viewController.dismissalDelegate = self

        present(viewController, animated: true, completion: nil)
    }

    func scanner(_ controller: BarcodeScannerViewController, didCaptureCode code: String, type: String) {
        print("Product's Bar code is :", code)
        controller.dismiss(animated: true, completion: nil)
    }

    func scanner(_ controller: BarcodeScannerViewController, didReceiveError error: Error) {
        print(error)
    }

    func scannerDidDismiss(_ controller: BarcodeScannerViewController) {
        controller.dismiss(animated: true, completion: nil)
    }
}

Aún así, y cualquier pregunta o desafío, consulte la aplicación de muestra aquí con el código fuente completo

swiftBoy
fuente
1

Creo que esto se puede hacer usando AVFramework, aquí está el código de muestra para hacer esto

import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate
{

    @IBOutlet weak var lblQRCodeResult: UILabel!
    @IBOutlet weak var lblQRCodeLabel: UILabel!

    var objCaptureSession:AVCaptureSession?
    var objCaptureVideoPreviewLayer:AVCaptureVideoPreviewLayer?
    var vwQRCode:UIView?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.configureVideoCapture()
        self.addVideoPreviewLayer()
        self.initializeQRView()
    }

    func configureVideoCapture() {
        let objCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        var error:NSError?
        let objCaptureDeviceInput: AnyObject!
        do {
            objCaptureDeviceInput = try AVCaptureDeviceInput(device: objCaptureDevice) as AVCaptureDeviceInput

        } catch let error1 as NSError {
            error = error1
            objCaptureDeviceInput = nil
        }
        objCaptureSession = AVCaptureSession()
        objCaptureSession?.addInput(objCaptureDeviceInput as! AVCaptureInput)
        let objCaptureMetadataOutput = AVCaptureMetadataOutput()
        objCaptureSession?.addOutput(objCaptureMetadataOutput)
        objCaptureMetadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        objCaptureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
    }

    func addVideoPreviewLayer() {
        objCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: objCaptureSession)
        objCaptureVideoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        objCaptureVideoPreviewLayer?.frame = view.layer.bounds
        self.view.layer.addSublayer(objCaptureVideoPreviewLayer!)
        objCaptureSession?.startRunning()
        self.view.bringSubviewToFront(lblQRCodeResult)
        self.view.bringSubviewToFront(lblQRCodeLabel)
    }

    func initializeQRView() {
        vwQRCode = UIView()
        vwQRCode?.layer.borderColor = UIColor.redColor().CGColor
        vwQRCode?.layer.borderWidth = 5
        self.view.addSubview(vwQRCode!)
        self.view.bringSubviewToFront(vwQRCode!)
    }

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        if metadataObjects == nil || metadataObjects.count == 0 {
            vwQRCode?.frame = CGRectZero
            lblQRCodeResult.text = "QR Code wans't found"
            return
        }
        let objMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
        if objMetadataMachineReadableCodeObject.type == AVMetadataObjectTypeQRCode {
            let objBarCode = objCaptureVideoPreviewLayer?.transformedMetadataObjectForMetadataObject(objMetadataMachineReadableCodeObject as AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject
            vwQRCode?.frame = objBarCode.bounds;
            if objMetadataMachineReadableCodeObject.stringValue != nil {
                lblQRCodeResult.text = objMetadataMachineReadableCodeObject.stringValue
            }
        }
    }
}
Jeff D
fuente
1

Aquí hay un código simple:

func scanbarcode()
{
    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())
        metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code]
    } else {
        failed()
        return
    }

    previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
    previewLayer.frame = view.layer.bounds;
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    view.layer.addSublayer(previewLayer);
    view.addSubview(closeBtn)
    view.addSubview(backimg)

    captureSession.startRunning();

}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func failed() {
    let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .Alert)
    ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
    presentViewController(ac, animated: true, completion: nil)
    captureSession = nil
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if (captureSession?.running == false) {
        captureSession.startRunning();
    }
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    if (captureSession?.running == true) {
        captureSession.stopRunning();
    }
}

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
    captureSession.stopRunning()

    if let metadataObject = metadataObjects.first {
        let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;

        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
        foundCode(readableObject.stringValue);
    }

   // dismissViewControllerAnimated(true, completion: nil)
}

func foundCode(code: String) {
    var createAccountErrorAlert: UIAlertView = UIAlertView()
    createAccountErrorAlert.delegate = self
    createAccountErrorAlert.title = "Alert"
    createAccountErrorAlert.message = code
    createAccountErrorAlert.addButtonWithTitle("ok")
    createAccountErrorAlert.addButtonWithTitle("Retry")
    createAccountErrorAlert.show()
    NSUserDefaults.standardUserDefaults().setObject(code, forKey: "barcode")
    NSUserDefaults.standardUserDefaults().synchronize()
    ItemBarcode = code
    print(code)
}

override func prefersStatusBarHidden() -> Bool {
    return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return .Portrait
}
shikha kochar
fuente
1

Si está desarrollando para iOS> 10.2 con Swift 4, puede probar mi solución. Mezclé esto y este tutorial y se me ocurrió un ViewController que escanea un código QR y print()lo elimina. También tengo un interruptor en mi interfaz de usuario para alternar la luz de la cámara, también podría ser útil. Por ahora solo lo probé en un iPhone SE, avíseme si no funciona en iPhones más nuevos.

Aqui tienes:

import UIKit
import AVFoundation

class QRCodeScanner: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    let captureSession: AVCaptureSession = AVCaptureSession()
    var videoPreviewLayer: AVCaptureVideoPreviewLayer?
    let qrCodeFrameView: UIView = UIView()
    var captureDevice: AVCaptureDevice?

    override func viewDidLoad() {
        // Get the back-facing camera for capturing videos
        let deviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInDualCamera], mediaType: AVMediaType.video, position: .back)

        captureDevice = deviceDiscoverySession.devices.first
        if captureDevice == nil {
            print("Failed to get the camera device")
            return
        }

        do {
            // Get an instance of the AVCaptureDeviceInput class using the previous device object.
            let input = try AVCaptureDeviceInput(device: captureDevice!)

            // Set the input device on the capture session.
            captureSession.addInput(input)

            // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
            let captureMetadataOutput = AVCaptureMetadataOutput()
            captureSession.addOutput(captureMetadataOutput)

            // Set delegate and use the default dispatch queue to execute the call back
            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            captureMetadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]

            // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.

            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)

            if let videoPreviewLayer = videoPreviewLayer {
                videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
                videoPreviewLayer.frame = view.layer.bounds
                view.layer.addSublayer(videoPreviewLayer)

                // Start video capture.
                captureSession.startRunning()

                if let hasFlash = captureDevice?.hasFlash, let hasTorch = captureDevice?.hasTorch {
                    if hasFlash && hasTorch {
                        view.bringSubview(toFront: bottomBar)
                        try captureDevice?.lockForConfiguration()
                    }
                }
            }

            // QR Code Overlay
            qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
            qrCodeFrameView.layer.borderWidth = 2
            view.addSubview(qrCodeFrameView)
            view.bringSubview(toFront: qrCodeFrameView)

        } catch {
            // If any error occurs, simply print it out and don't continue any more.
            print("Error: \(error)")
            return
        }
    }

    // MARK: Buttons and Switch

    @IBAction func switchFlashChanged(_ sender: UISwitch) {
        do {
            if sender.isOn {
                captureDevice?.torchMode = .on
            } else {
                captureDevice?.torchMode = .off
            }
        }
    }

    // MARK: AVCaptureMetadataOutputObjectsDelegate

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

        // Check if the metadataObjects array is not nil and it contains at least one object.
        if metadataObjects.count == 0 {
            qrCodeFrameView.frame = CGRect.zero
            return
        }

        // Get the metadata object.
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject

        if metadataObj.type == AVMetadataObject.ObjectType.qr {
            // If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
            let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
            qrCodeFrameView.frame = barCodeObject!.bounds

            print("QR Code: \(metadataObj.stringValue)")
        }
    }
}
Paul Spiesberger
fuente
0

A veces puede ser útil también para generar códigos QR . Hay una excelente biblioteca de C para esto que funciona a las mil maravillas. Se llama libqrencode . Escribir una vista personalizada para mostrar el código QR no es tan difícil y se puede hacer con una comprensión básica de QuartzCore.

GorilaPatch
fuente
¿Conoces algún tutorial sobre cómo incluir esto en un proyecto xCode de iOS?
james
¿Le importaría compartir cómo generó la vista utilizando Quartcore? sería un gran ahorro de tiempo: P
ThomasRS
Eso es correcto. Sin embargo, asegúrese de cumplir con la licencia de software, la biblioteca se publica con.
GorillaPatch
Esta pregunta es sobre el reconocimiento, no sobre la generación.
MonsieurDart
0

puede verificar ZBarSDK para leer el código QR y los códigos ECN / ISBN, es fácil de integrar, pruebe el siguiente código.

- (void)scanBarcodeWithZBarScanner
  {
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;

ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here

// EXAMPLE: disable rarely used I2/5 to improve performance
 [scanner setSymbology: ZBAR_I25
               config: ZBAR_CFG_ENABLE
                   to: 0];

//Get the return value from controller
[reader setReturnBlock:^(BOOL value) {

}

y en didFinishPickingMediaWithInfo obtenemos el valor del código de barras.

    - (void) imagePickerController: (UIImagePickerController*) reader
   didFinishPickingMediaWithInfo: (NSDictionary*) info
   {
    // ADD: get the decode results
    id<NSFastEnumeration> results =
    [info objectForKey: ZBarReaderControllerResults];
    ZBarSymbol *symbol = nil;
    for(symbol in results)
    // EXAMPLE: just grab the first barcode
    break;

    // EXAMPLE: do something useful with the barcode data
    barcodeValue = symbol.data;

    // EXAMPLE: do something useful with the barcode image
    barcodeImage =   [info objectForKey:UIImagePickerControllerOriginalImage];
    [_barcodeIV setImage:barcodeImage];

    //set the values for to TextFields
    [self setBarcodeValue:YES];

    // ADD: dismiss the controller (NB dismiss from the *reader*!)
    [reader dismissViewControllerAnimated:YES completion:nil];
   }
Amit Shelgaonkar
fuente