Como digitalizar códigos de barras no iOS?

189

Como posso simplesmente escanear códigos de barras no iPhone e / ou iPad?

Stefan
fonte
7
Infelizmente, a câmera do iPhone atualmente é péssima para a leitura de códigos de barras, pois sua lente está com foco fixo em ∞. Boa sorte embora!
Alastair Stuart
1
Apenas resolvi esse problema, então escreverei minhas observações. Eu testei algumas opções. RSBarcodes_Swift - foi fácil de integrar, mas teve um desempenho muito ruim. ZBarSDK - também foi fácil de implementar, apesar de poucos serem pesquisados ​​no Google para descobrir como. Mas teve um desempenho muito bom (não varreu a matriz de dados e outros códigos raros) funciona muito bem para códigos de barras / QRCode. Mas Scandit foi o melhor de todos. Super rápido, digitaliza tudo. infelizmente custa bastante.
Katafalkas 02/02

Respostas:

82

Produzimos o aplicativo 'Barcodes' para o iPhone. Pode decodificar códigos QR. O código fonte está disponível no projeto zxing ; especificamente, você deseja dar uma olhada no cliente do iPhone e na porta C ++ parcial da biblioteca principal . A porta é um pouco antiga, desde a versão 0.9 do código Java, mas ainda deve funcionar razoavelmente bem.

Se você precisar digitalizar outros formatos, como os formatos 1D, poderá continuar a porta do código Java dentro deste projeto para C ++.

EDIT: os códigos de barras e o iphonecódigo do projeto foram retirados no início de 2014.

Sean Owen
fonte
Sean, que tipo de licença ele usa. Quero criar um aplicativo pago que use o Zbar. Isso é possível sob o contrato de licença?
Radu
1
Só para esclarecer, neste momento, o ZXing no iPhone suporta apenas códigos QR?
RefuX
Acredito que mais tenha sido portado para C ++, mas a porta ainda é um eco áspero e desatualizado do código Java, infelizmente. Então, sim, mais é suportado, embora talvez não esteja bem.
Sean Owen
O ZXing para iPhone ainda tem vazamentos de memória em 1,7 ver.
Yoon Lee
A partir da lista de problemas no git do zXing, entendo que só podemos ler códigos de barras no modo paisagem.
Sagrian
81

Confira o ZBar lê códigos QR e ECN / ISBN e está disponível sob a licença LGPL v2.

Vijay
fonte
5
Parcialmente correta. O ZBar.app é licenciado sob a Licença Apache (Versão 2.0), no entanto, a biblioteca é licenciada sob o LGPL v2.
26511 Sean
3
Infelizmente a licença exige que você compartilhe arquivos objeto de seu aplicativo com qualquer pessoa que solicita-los .. confira zbar.sourceforge.net/iphone/sdkdoc/licensing.html
Ben Clayton
1
@BenClayton, o que significa compartilhar os arquivos de objetos do aplicativo?
Dejell
@ Odelya Enviando os arquivos .o como gerados pelo Xcode para qualquer pessoa, teoricamente permitindo que eles criem seu aplicativo. Definitivamente, não estou feliz em fazer isso (especialmente para meus clientes), portanto o ZBar está fora de questão para nós. A página de licenciamento da ZBar sugere que você "espere que ninguém as solicite!"
Ben Clayton
@BenClayton A. Obrigado B. Eu poderia alterar o componente se alguém perguntar e exigir dos usuários do aplicativo já baixados, que baixem uma versão mais recente. É o suficiente? C. Então, qual biblioteca você está usando?
Dejell
56

Assim como no lançamento, iOS7você não precisa mais usar uma estrutura ou biblioteca externa. O ecossistema iOS com AVFoundation agora suporta totalmente a verificação quase todos os códigos, desde QR através de EAN até UPC.

Basta dar uma olhada na Nota técnica e no guia de programação da AVFoundation. AVMetadataObjectTypeQRCodeé seu amigo.

Aqui está um bom tutorial que mostra passo a passo: biblioteca de verificação de código QR do iPhone iOS7

Apenas um pequeno exemplo de como configurá-lo:

#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];
}
Alexander
fonte
1
Se você deseja detectar o código de barras da imagem no iOS8, este tutorial pode ser útil.
NSDeveloper
Eu descobri que eu tinha que ligar startRunningna sessão para obter o código acima para trabalho em caso que ajuda a alguém :)
Chris
13

A câmera do iPhone 4 é mais do que um código de barras. A biblioteca de códigos de barras do cruzamento de zebra possui uma bifurcação no github zxing-iphone . É de código aberto.

Aris Bartee
fonte
1
Sua postagem parece sugerir que essa porta do ZXing pode digitalizar mais do que apenas QRCodes? É esse o caso?
RefuX 26/04
4
O fork do github parece estar morto, conforme indicado neste problema: github.com/joelind/zxing-iphone/issues/3
Josh Brown
10

O liteqr é um "Lite QR Reader no Objective C portado do zxing" no github e tem suporte para o Xcode 4.

Josh Brown
fonte
10

Existem duas bibliotecas principais:

  • ZXing uma biblioteca escrita em Java e, em seguida, portada para o Objective C / C ++ (somente código QR). E uma outra porta para ObjC foi feita, por TheLevelUp: ZXingObjC

  • ZBar, um software de código aberto para leitura de códigos de barras, baseado em C.

De acordo com meus experimentos, o ZBar é muito mais preciso e rápido que o ZXing, pelo menos no iPhone.

MonsieurDart
fonte
Parece-me que ZXingObjC é o que deve ser levado ao topo com mais votos até agora. Eu nunca usei isso ainda , mas a descrição diz que é sobre a paridade com ZXing 2.0.
Shaolo 03/12/12
A licença do ZBar exige que você ofereça os arquivos de objeto aos usuários, para que eles possam executá-lo e modificar sua biblioteca também.
Dejell
Eu recomendo o ZXingObjC
Dejell
7

Você pode encontrar outra solução iOS nativa usando o Swift 4 e o Xcode 9 abaixo. AVFoundationEstrutura nativa usada nesta solução.

A primeira parte é a subclasse a UIViewControllerque possui funções de configuração e manipulador relacionadas 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)
    }

}

A segunda parte é a extensão de nossa UIViewControllersubclasse para AVCaptureMetadataOutputObjectsDelegateonde capturamos as saídas capturadas.

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Atualização para o Swift 4.2

.UIApplicationWillEnterForegroundmuda como UIApplication.willEnterForegroundNotification.

abdullahselek
fonte
isso fornecerá o nome, tamanho, preço, URL do produto, moeda, nome do arquivo? ou ele vai dar apenas o @abdullahselek número de código de barras
R. Mohan
@ R.Mohan está relacionado ao código de barras que você lê. Verifique AVCaptureMetadataOutput e AVMetadataMachineReadableCodeObject e tente ler metadataObjectsdentro da função handleCapturedOutput .
abdullahselek
Ok, vai tentar isso. Obrigado pela resposta @abdullahselek
R. Mohan
5

Não tenho certeza se isso vai ajudar, mas aqui está um link para uma biblioteca de código QR de código aberto . Como você pode ver, algumas pessoas já usaram isso para criar aplicativos para o iphone.

A Wikipedia tem um artigo explicando o que são códigos QR . Na minha opinião, os códigos QR são muito mais adequados ao objetivo do que o código de barras padrão no que diz respeito ao iphone, pois foi projetado para esse tipo de implementação.

lexx
fonte
5

Se o suporte ao iPad 2 ou iPod Touch for importante para o seu aplicativo, eu escolheria um SDK do scanner de código de barras que pode decodificar códigos de barras em imagens borradas, como o nosso SDK do scanner de código de barras Scandit para iOS e Android. A decodificação de imagens borradas de código de barras também é útil em telefones com câmeras com foco automático, porque o usuário não precisa esperar pelo foco automático.

O Scandit vem com um plano de preços comunitário gratuito e também possui uma API do produto que facilita a conversão de números de código de barras em nomes de produtos.

(Aviso: sou co-fundador da Scandit)

floerkem
fonte
4

Você pode dar uma olhada no código-fonte do leitor DataMatrix para iPhone de Stefan Hafeneger ( projeto do Google Code ; postagem de blog arquivada ), se ainda estiver disponível.

Galego
fonte
Como está sua experiência com este aplicativo? Para mim, são necessários 10s ou mais para decodificar um código de barras simples da matriz de dados!
Febj4de
1
O link foi alterado para stefan.hafeneger.name/blog/2009/09/08/…
Suresh Varma
1
Link direto (acho que o Google não vai desaparecer por um tempo) code.google.com/p/barcodeapp
alguém sabe qual é o nome oficial do aplicativo de Stefan na appstore? Gostaria de fazer o download antes de mergulhar no código real.
macutan
3

O problema com a câmera do iPhone é que os primeiros modelos (dos quais existem toneladas em uso) têm uma câmera de foco fixo que não pode tirar fotos em foco em distâncias inferiores a 2 pés. As imagens estão tremidas e distorcidas e, se tiradas a uma distância maior, não há detalhes / informações suficientes no código de barras.

Algumas empresas desenvolveram aplicativos para iPhone que podem acomodar isso usando tecnologias avançadas de desfoque. Esses aplicativos podem ser encontrados na loja de aplicativos da Apple: pic2shop, RedLaser e ShopSavvy. Todas as empresas anunciaram que também têm SDKs disponíveis - alguns de forma gratuita ou muito preferencial, confira esse.

Nas Banov
fonte
Eu tentei usar o ShopSavvy com um iPhone 3G. É divertido, mas trava com muita freqüência e é muito, muito difícil ler códigos de barras planos muito claros.
James Moore
1
E eu apenas tentei pic2shop. Citação da minha noiva: "isso deve facilitar nossas vidas COMO?" É um aplicativo fofo, mas não é realmente capaz de ler um código de barras, tanto quanto eu posso dizer.
James Moore
Qual formato você tentou ler? Tentei usar o pic2shop para digitalizar o EAN e funciona muito bem. A taxa de licença é cara, ainda mais do que o RedLaser.
Iamj4de
2

com Swift 5 é simples e super rápido !!

Você só precisa adicionar vagens de cacau "BarcodeScanner" aqui está o código completo

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

Certifique-se de adicionar permissão de câmera no seu arquivo .plist

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

E adicione o Scanner e lide com o resultado no seu ViewController dessa maneira

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)
    }
}

Ainda assim, e qualquer dúvida ou desafio, verifique o exemplo de aplicativo aqui com o código fonte completo

swiftBoy
fonte
1

Eu acredito que isso pode ser feito usando o AVFramework, aqui está o código de exemplo para fazer isso

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
fonte
1

Aqui está um código simples:

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
fonte
1

Se você está desenvolvendo para iOS> 10.2 com Swift 4, pode tentar minha solução. Eu misturei este e este tutorial e criei um ViewController que verifica um QR Code e print()ele sai. Também tenho um Switch na minha interface do usuário para alternar a luz da câmera, pode ser útil também. Por enquanto, só testei em um iPhone SE, por favor, deixe-me saber se ele não funciona em iPhones mais recentes.

Aqui está:

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
fonte
0

Às vezes, também pode ser útil gerar códigos QR . Existe uma excelente biblioteca C para isso, que funciona como um encanto. É chamado libqrencode . Escrever uma exibição personalizada para exibir o código QR não é tão difícil e pode ser feito com um entendimento básico do QuartzCore.

GorillaPatch
fonte
você conhece algum tutorial sobre como incluir isso em um projeto iOS xCode?
james
você se importaria de compartilhar como gerou a exibição usando quartcore? seria uma grande economia de tempo: P
ThomasRS 1/11/11
Isso está certo. No entanto, verifique se você é compatível com a licença do software, com a qual a biblioteca foi publicada.
GorillaPatch
Esta questão é sobre reconhecimento, não geração.
MonsieurDart
0

você pode verificar o ZBarSDK para ler códigos QR e códigos ECN / ISBN; é fácil integrar; tente o código a seguir.

- (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) {

}

e em didFinishPickingMediaWithInfo, obtemos o valor do 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
fonte