Come posso scansionare i codici a barre su iOS?


189

Come posso semplicemente scansionare i codici a barre su iPhone e / o iPad?


7
Purtroppo, la fotocamera dell'iPhone è attualmente terribile per la lettura di codici a barre in quanto l'obiettivo è a fuoco fisso su ∞. Buona fortuna però!
Alastair Stuart

1
Ho appena risolto questo problema, quindi scriverò le mie osservazioni. Ho testato alcune opzioni. RSBarcodes_Swift - era facile da integrare, ma aveva prestazioni molto scarse. ZBarSDK - è stato anche facile da implementare, anche se pochi hanno cercato su Google per scoprire come. Ma aveva prestazioni davvero buone (non ha scansionato datamatrix e altri codici rari) funziona davvero bene per i codici a barre / QRCode. Ma Scandit era il migliore di tutti. Super veloce, scansiona tutto. purtroppo costa parecchio.
Katafalkas,

Risposte:


82

Abbiamo prodotto l'applicazione "Codici a barre" per iPhone. Può decodificare i codici QR. Il codice sorgente è disponibile dal progetto zxing ; in particolare, si desidera dare un'occhiata al client iPhone e alla porta C ++ parziale della libreria principale . La porta è un po 'vecchia, a partire dalla versione 0.9 del codice Java, ma dovrebbe comunque funzionare abbastanza bene.

Se è necessario eseguire la scansione di altri formati, come i formati 1D, è possibile continuare la porta del codice Java all'interno di questo progetto su C ++.

EDIT: i codici a barre e il iphonecodice nel progetto sono stati ritirati all'inizio del 2014.


Sean che tipo di licenza utilizza. Voglio creare un'app a pagamento che utilizza Zbar. È possibile in base all'accordo di licenza?
Radu,

1
Giusto per essere chiari, in questo momento, ZXing su iPhone supporta solo i codici QR?
RefuX,

Credo che più sia stato portato su C ++, ma purtroppo la porta è ancora un'eco approssimativa e obsoleta del codice Java. Quindi, sì, è supportato di più, anche se forse non va bene.
Sean Owen,

ZXing per iPhone presenta ancora perdite di memoria di 1,7 ver.
Yoon Lee,

Dalla lista dei problemi su git di zXing capisco che possiamo scansionare i codici a barre solo in modalità orizzontale.
Sagrian,

81

Dai un'occhiata a ZBar legge i codici QR e i codici ECN / ISBN ed è disponibile come sotto licenza LGPL v2.


5
Parzialmente corretto. ZBar.app è concesso in licenza con licenza Apache (versione 2.0), tuttavia la libreria è concessa in licenza con LGPL v2.
Sean,

3
Purtroppo la licenza richiede di condividere i file oggetto della tua app con chiunque lo richieda. Dai
Ben Clayton,

1
@BenClayton cosa significa condividere i file oggetto dell'app?
Dejell

@Odelya Invio di file .o come generato da Xcode a chiunque, teoricamente consentendo loro di creare la tua app. Non sono assolutamente contento di farlo (specialmente per i miei clienti), quindi ZBar è fuori discussione per noi. La pagina delle licenze di ZBar suggerisce che dovresti semplicemente "sperare che nessuno li richieda!"
Ben Clayton,

@BenClayton A. Grazie B. Potrei cambiare il componente se qualcuno chiedesse e richiedesse agli utenti delle app già scaricate di scaricare una versione più recente. È abbastanza? C. Quindi quale libreria stai usando?
Dejell

56

Come per il rilascio iOS7, non è più necessario utilizzare un framework o una libreria esterni. L'ecosistema iOS con AVFoundation ora supporta completamente la scansione di quasi tutti i codici da QR su EAN a UPC.

Dai un'occhiata alla nota tecnica e alla guida alla programmazione di AVFoundation. AVMetadataObjectTypeQRCodeÈ tuo amico.

Ecco un bel tutorial che lo mostra passo dopo passo: libreria di scansione del codice QR per iPhone iOS7

Solo un piccolo esempio su come 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];
}

1
Se desideri rilevare il codice a barre dall'immagine su iOS8, questo tutorial può essere utile.
NSDeveloper

Ho scoperto che dovevo chiamare startRunningla sessione per far funzionare il codice sopra nel caso in cui ciò aiuti qualcuno :)
Chris

13

La fotocamera dell'iPhone 4 è molto più che un capabale di codici a barre. La libreria di codici a barre di strisce pedonali ha un fork su github zxing-iphone . È open-source.


1
Il tuo post sembra implicare che questa porta di ZXing può scansionare più di un semplice QRCode? È così?
RefuX,

4
Il fork di github sembra essere morto, come indicato da questo numero: github.com/joelind/zxing-iphone/issues/3
Josh Brown,

10

liteqr è un "Lettore QR Lite in Objective C portato da zxing" su github e ha il supporto per Xcode 4.


10

Esistono due principali biblioteche:

  • ZXing di una libreria scritta in Java e quindi trasferita su Objective C / C ++ (solo codice QR). E un'altra porta per ObjC è stata realizzata da TheLevelUp: ZXingObjC

  • ZBar è un software open source per la lettura di codici a barre, basato su C.

Secondo i miei esperimenti, ZBar è molto più preciso e veloce di ZXing, almeno su iPhone.


Mi sembra che ZXingObjC sia quello che dovrebbe essere portato in cima con il maggior numero di voti ormai. Io non ho usato ancora , ma la descrizione dice che è sulla parità con ZXing 2.0.
Shaolo,

La licenza ZBar richiede di offrire i file oggetto agli utenti, in modo che possano eseguirlo e modificare anche la loro libreria.
Dejell

Consiglio ZXingObjC
Dejell


7

Puoi trovare un'altra soluzione iOS nativa usando Swift 4 e Xcode 9 in basso. Quadro nativo AVFoundationutilizzato con in questa soluzione.

La prima parte è una sottoclasse per la UIViewControllerquale sono correlate funzioni di configurazione e gestione 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 seconda parte è l'estensione della nostra UIViewControllersottoclasse per AVCaptureMetadataOutputObjectsDelegatecui catturiamo gli output acquisiti.

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Aggiornamento per Swift 4.2

.UIApplicationWillEnterForegroundcambia come UIApplication.willEnterForegroundNotification.


questo fornirà il nome del prodotto, la dimensione, il prezzo, l'URL del prodotto, la valuta, il nome del negozio? o fornirà solo il numero di codice a barre @abdullahselek
R. Mohan,

@ R.Mohan è legato al codice a barre che leggi. Controlla AVCaptureMetadataOutput e AVMetadataMachineReadableCodeObject e prova a leggere metadataObjectsall'interno della funzione handleCapturedOutput .
abdullahselek,

Ok, ci proverò. Grazie per la risposta @abdullahselek
R. Mohan,

5

Non sono sicuro se questo aiuterà, ma ecco un link a una libreria di codici QR open source . Come puoi vedere, un paio di persone lo hanno già usato per creare app per iPhone.

Wikipedia ha un articolo che spiega quali sono i codici QR . A mio avviso, i codici QR sono molto più adatti allo scopo rispetto al codice a barre standard per quanto riguarda l'iPhone in quanto è stato progettato per questo tipo di implementazione.


5

Se il supporto per iPad 2 o iPod Touch è importante per la tua applicazione, sceglierei un SDK per scanner di codici a barre in grado di decodificare i codici a barre in immagini sfocate, come il nostro scanner SDK per codici a barre Scandit per iOS e Android. La decodifica di immagini sfocate di codici a barre è utile anche sui telefoni con fotocamere autofocus perché l'utente non deve attendere l'avvio dell'autofocus.

Scandit viene fornito con un piano tariffario comunitario gratuito e ha anche un'API del prodotto che semplifica la conversione dei numeri di codice a barre in nomi di prodotti.

(Dichiarazione di non responsabilità: sono un co-fondatore di Scandit)


4

Com'è la tua esperienza con questa app? Per me ci vogliono almeno 10 secondi per decodificare un semplice codice a barre datamatrix!
iamj4de,


1
Link diretto (non credo che Google scomparirà per un po ') code.google.com/p/barcodeapp

qualcuno sa qual è il nome ufficiale dell'app di Stefan sull'appstore? Vorrei scaricarlo prima di immergermi nel codice reale.
macutan,

3

Il problema con la fotocamera dell'iPhone è che i primi modelli (di cui ce ne sono molti in uso) hanno una fotocamera a fuoco fisso che non può scattare foto a fuoco per distanze inferiori a 2 piedi. Le immagini sono sfocate e distorte e se prese da una maggiore distanza non ci sono abbastanza dettagli / informazioni dal codice a barre.

Alcune aziende hanno sviluppato app per iPhone che possono adattarsi a ciò utilizzando tecnologie avanzate di sfocatura. Quelle applicazioni che puoi trovare sull'app store Apple: pic2shop, RedLaser e ShopSavvy. Tutte le aziende hanno annunciato di avere anche SDK disponibili - alcuni in termini gratuiti o molto preferenziali, controlla quello.


Ho provato a utilizzare ShopSavvy con un iPhone 3G. È divertente, ma si blocca molto frequentemente e fa fatica a leggere codici a barre piatti molto chiari.
James Moore,

1
E ho appena provato Pic2shop. Citazione della mia fidanzata: "Questo dovrebbe rendere le nostre vite più facili COME?" È un'app carina, ma in realtà non è in grado di leggere un codice a barre per quanto ne so.
James Moore,

Quale formato hai provato a leggere? Ho provato a usare pic2shop per scansionare EAN e funziona molto bene. Il costo della licenza è costoso, anche più di RedLaser.
iamj4de,

2

con Swift 5 è semplice e super veloce !!

Hai solo bisogno di aggiungere baccelli di cacao "BarcodeScanner" qui è il codice completo

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

Assicurati di aggiungere l'autorizzazione Camera nel tuo file .plist

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

Aggiungi scanner e gestisci i risultati nel tuo ViewController in questo modo

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

Comunque e per qualsiasi domanda o sfida, controlla qui l'applicazione di esempio con il codice sorgente completo



1

Credo che questo possa essere fatto usando AVFramework, ecco il codice di esempio per farlo

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

1

Ecco un semplice codice:

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
}

1

Se stai sviluppando per iOS> 10.2 con Swift 4, puoi provare la mia soluzione. Ho confuso questo e questo tutorial e mi è venuto in mente un ViewController che scansiona un codice QR e print()lo fa uscire. Ho anche un interruttore nella mia interfaccia utente per attivare / disattivare la luce della fotocamera, potrebbe anche essere utile. Per ora l'ho provato solo su un iPhone SE, per favore fatemi sapere se non funziona su iPhone più recenti.

Ecco qui:

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

0

A volte può essere utile anche generare codici QR . C'è una superba libreria C per questo che funziona come un fascino. Si chiama libqrencode . Scrivere una vista personalizzata per visualizzare il codice QR non è poi così difficile e può essere fatto con una conoscenza di base di QuartzCore.


conosci qualche tutorial su come includerlo in un progetto iOS xCode?
Giacomo,

ti dispiacerebbe condividere come hai generato la vista usando quartcore? sarebbe un grande risparmio di tempo: P
ThomasRS

È giusto. Tuttavia, assicurati di essere conforme con la licenza del software, la libreria è pubblicata con.
GorillaPatch,

Questa domanda riguarda il riconoscimento, non la generazione.
Monsieur,

0

puoi controllare ZBarSDK per leggere i codici QR e i codici ECN / ISBN è semplice da integrare prova il seguente codice.

- (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 in didFinishPickingMediaWithInfo otteniamo il valore del codice a barre.

    - (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];
   }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.