Comment puis-je scanner des codes-barres sur iOS?

190

Comment puis-je simplement scanner des codes-barres sur iPhone et / ou iPad?

Stefan
la source
7
Malheureusement, la caméra de l'iPhone est actuellement terrible pour la lecture des codes-barres car son objectif est mis au point sur ∞. Bonne chance!
Alastair Stuart
1
Je viens de résoudre ce problème, je vais donc écrire mes observations. J'ai testé quelques options. RSBarcodes_Swift - était facile à intégrer, mais avait de très mauvaises performances. ZBarSDK - était également facile à mettre en œuvre, mais il a fallu peu de recherches sur Google pour trouver comment. Mais avoir de très bonnes performances (ne pas numériser datamatrix et autres codes rares) fonctionne très bien pour les codes à barres / QRCode. Mais Scandit était le meilleur de tous. Super rapide, scanne tout. coûte malheureusement beaucoup.
Katafalkas le

Réponses:

84

Nous avons produit l'application 'Barcodes' pour l'iPhone. Il peut décoder les codes QR. Le code source est disponible à partir du projet zxing ; Plus précisément, vous voulez jeter un coup d'œil au client iPhone et au port C ++ partiel de la bibliothèque principale . Le port est un peu vieux, à partir de la version 0.9 du code Java environ, mais devrait quand même fonctionner raisonnablement bien.

Si vous avez besoin de scanner d'autres formats, comme les formats 1D, vous pouvez continuer le portage du code Java dans ce projet vers C ++.

EDIT: Les codes à barres et le iphonecode du projet ont été supprimés vers le début de 2014.

Sean Owen
la source
Sean quel type de licence utilise-t-il. Je souhaite créer une application payante qui utilise Zbar. Est-ce possible en vertu du contrat de licence?
Radu
1
Pour être clair, à ce stade, ZXing sur l'iPhone ne prend en charge que les codes QR?
RefuX
Je crois que plus a été porté en C ++, mais le port est toujours un écho approximatif et obsolète du code Java malheureusement. Donc, oui, plus est pris en charge mais peut-être pas bien.
Sean Owen
ZXing pour iPhone a encore des fuites de mémoire de 1.7 ver.
Yoon Lee
Je comprends de la liste des problèmes sur git de zXing que nous ne pouvons scanner le code-barres qu'en mode paysage.
Sagrian
81

Vérifiez que ZBar lit le code QR et les codes ECN / ISBN et est disponible sous la licence LGPL v2.

Vijay
la source
5
Partiellement correct. Le ZBar.app est sous licence Apache (version 2.0), mais la bibliothèque est sous licence LGPL v2.
Sean
3
Malheureusement, la licence vous oblige à partager les fichiers objets de votre application avec quiconque en fait la demande. Consultez zbar.sourceforge.net/iphone/sdkdoc/licensing.html
Ben Clayton
1
@BenClayton Que signifie partager les fichiers objets de l'application?
Dejell
@Odelya Envoi des fichiers .o générés par Xcode à n'importe qui, leur permettant théoriquement de créer votre application. Je ne suis certainement pas content de faire ça (surtout pour mes clients) donc ZBar est hors de question pour nous. La page des licences ZBar suggère que vous devriez simplement «espérer que personne ne les demandera!
Ben Clayton
@BenClayton A. Merci B. Je pourrais changer le composant si quelqu'un demande et demande aux utilisateurs de l'application déjà téléchargés de télécharger une version plus récente. Est-ce suffisant? C. Alors, quelle bibliothèque utilisez-vous?
Dejell
56

Comme avec la sortie, iOS7vous n'avez plus besoin d'utiliser un framework ou une bibliothèque externe. L'écosystème iOS avec AVFoundation prend désormais entièrement en charge la numérisation de presque tous les codes de QR sur EAN vers UPC.

Jetez un œil à la note technique et au guide de programmation AVFoundation. AVMetadataObjectTypeQRCodeest votre ami.

Voici un joli tutoriel qui le montre étape par étape: Bibliothèque de scan de code QR iPhone iOS7

Juste un petit exemple sur la façon de le configurer:

#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];
}
Alexandre
la source
1
Si vous souhaitez détecter le code-barres de l'image sur iOS8, ce tutoriel peut être utile.
NSDeveloper
J'ai trouvé que je devais appeler startRunningla session pour que le code ci-dessus fonctionne au cas où cela aiderait quelqu'un :)
Chris
13

L'appareil photo de l'iPhone 4 est plus que capable de créer des codes-barres. La bibliothèque de codes à barres de passage de zèbres a une fourchette sur github zxing-iphone . C'est open-source.

Aris Bartee
la source
1
Votre message semble impliquer que ce port de ZXing peut scanner plus que de simples QRCodes? Est-ce le cas?
RefuX
4
Le fork de github semble être mort, comme indiqué par ce numéro: github.com/joelind/zxing-iphone/issues/3
Josh Brown
10

liteqr est un "Lite QR Reader en Objective C porté depuis zxing" sur github et prend en charge Xcode 4.

Josh Brown
la source
10

Il existe deux bibliothèques principales:

  • ZXing une bibliothèque écrite en Java puis portée en Objective C / C ++ (QR code uniquement). Et un autre port vers ObjC a été fait, par TheLevelUp: ZXingObjC

  • ZBar est un logiciel open source pour la lecture de codes à barres, basé sur C.

D'après mes expériences, ZBar est beaucoup plus précis et rapide que ZXing, du moins sur iPhone.

MonsieurDart
la source
Il me semble que ZXingObjC est celui qui devrait être poussé au sommet avec le plus de votes maintenant. Je ne l' ai pas utilisé encore , mais la description dit qu'il est sur la parité avec ZXing 2.0.
Shaolo
La licence ZBar vous oblige à offrir les fichiers objets aux utilisateurs, afin qu'ils puissent l'exécuter et puissent également modifier leur bibliothèque.
Dejell
Je recommande ZXingObjC
Dejell
7

Vous pouvez trouver une autre solution iOS native utilisant Swift 4 et Xcode 9 ci-dessous. AVFoundationFramework natif utilisé dans cette solution.

La première partie est une sous-classe UIViewControllerdont les fonctions de configuration et de gestion sont associées 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 deuxième partie est l'extension de notre UIViewControllersous-classe AVCaptureMetadataOutputObjectsDelegateoù nous capturons les sorties capturées.

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Mise à jour pour Swift 4.2

.UIApplicationWillEnterForegroundchange comme UIApplication.willEnterForegroundNotification.

abdullahselek
la source
cela donnera-t-il le nom du produit, la taille, le prix, l'URL du produit, la devise, le nom du magasin? ou il donnera juste le numéro de code à barres @abdullahselek
R. Mohan
@ R.Mohan c'est lié au code à barres que vous lisez. Veuillez vérifier AVCaptureMetadataOutput et AVMetadataMachineReadableCodeObject et essayez de lire metadataObjectsà l'intérieur du handleCapturedOutput fonction .
abdullahselek
Ok, j'essaierai ça. Merci pour la réponse @abdullahselek
R. Mohan
5

Je ne sais pas si cela aidera mais voici un lien vers une bibliothèque de codes QR open source . Comme vous pouvez le voir, quelques personnes l'ont déjà utilisé pour créer des applications pour l'iphone.

Wikipedia a un article expliquant ce que sont les codes QR . À mon avis, les codes QR sont beaucoup plus adaptés que le code-barres standard en ce qui concerne l'iphone car il a été conçu pour ce type d'implémentation.

lexx
la source
5

Si la prise en charge de l'iPad 2 ou de l'iPod Touch est importante pour votre application, je choisirais un SDK de scanner de codes à barres capable de décoder les codes à barres dans des images floues, comme notre SDK de scanner de codes à barres Scandit pour iOS et Android. Le décodage d'images de codes à barres floues est également utile sur les téléphones équipés d'appareils photo à mise au point automatique, car l'utilisateur n'a pas à attendre que la mise au point automatique se déclenche.

Scandit est livré avec un plan de prix communautaire gratuit et dispose également d'une API de produit qui facilite la conversion des numéros de codes à barres en noms de produits.

(Avertissement: je suis co-fondateur de Scandit)

floerkem
la source
4

Vous pouvez jeter un œil au code source iPhone DataMatrix Reader de Stefan Hafeneger ( projet Google Code ; article de blog archivé ) s'il est toujours disponible.

Galvégien
la source
Quelle est votre expérience avec cette application? Pour moi, il faut 10 s ou plus pour décoder un simple code-barres datamatrix!
iamj4de
1
Le lien est changé en stefan.hafeneger.name/blog/2009/09/08/…
Suresh Varma
1
Lien direct (je ne pense pas que Google disparaîtra pendant un certain temps) code.google.com/p/barcodeapp
est-ce que quelqu'un sait quel est le nom officiel de l'application de Stefan sur l'Appstore? J'aimerais le télécharger avant de plonger dans le code réel.
macutan
3

Le problème avec l'appareil photo iPhone est que les premiers modèles (dont il y en a des tonnes en cours d'utilisation) ont un appareil photo à mise au point fixe qui ne peut pas prendre de photo au point sur des distances inférieures à 2 pieds. Les images sont floues et déformées et si elles sont prises à une plus grande distance, il n'y a pas assez de détails / informations du code-barres.

Quelques entreprises ont développé des applications iPhone qui peuvent s'adapter à cela en utilisant des technologies avancées de réduction du flou. Ces applications que vous pouvez trouver sur l'App Store d'Apple: pic2shop, RedLaser et ShopSavvy. Toutes les entreprises ont annoncé qu'elles avaient également des SDK disponibles - certains à des conditions gratuites ou très préférentielles, vérifiez celui-là.

Nas Banov
la source
J'ai essayé d'utiliser ShopSavvy avec un iPhone 3G. C'est amusant, mais se bloque très fréquemment et il est très difficile de lire des codes-barres plats très clairs.
James Moore
1
Et je viens d'essayer pic2shop. Citation de ma fiancée: "c'est censé nous faciliter la vie COMMENT?" C'est une application mignonne, mais ce n'est pas vraiment capable de lire un code-barres pour autant que je sache.
James Moore
Quel format avez-vous essayé de lire? J'ai essayé d'utiliser pic2shop pour scanner EAN et cela fonctionne très bien. Les frais de licence sont cependant chers, encore plus que RedLaser.
iamj4de
3

avec Swift 5 c'est simple et super rapide !!

Il vous suffit d'ajouter des cabosses de cacao "BarcodeScanner" voici le code complet

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

Assurez-vous d'ajouter l'autorisation de la caméra dans votre fichier .plist

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

Et ajoutez le scanner et gérez le résultat dans votre ViewController de cette façon

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

Encore et toute question ou défi, veuillez vérifier l'exemple d'application ici avec le code source complet

swiftBoy
la source
1

Je pense que cela peut être fait en utilisant AVFramework, voici l'exemple de code pour le faire

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
la source
1

Voici un code 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
la source
1

Si vous développez pour iOS> 10.2 avec Swift 4, vous pouvez essayer ma solution. J'ai mélangé ceci et ce tutoriel et suis venu avec un ViewController qui scanne un QR Code et print()le sort. J'ai également un commutateur dans mon interface utilisateur pour activer l'éclairage de la caméra, cela pourrait également être utile. Pour l'instant, je ne l'ai testé que sur un iPhone SE, veuillez me faire savoir si cela ne fonctionne pas sur les nouveaux iPhones.

Voici:

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
la source
0

Parfois, il peut également être utile de générer des codes QR . Il existe une superbe bibliothèque C pour cela qui fonctionne à merveille. Il s'appelle libqrencode . Écrire une vue personnalisée pour afficher le code QR n'est alors pas si difficile et peut être fait avec une compréhension de base de QuartzCore.

GorillaPatch
la source
connaissez-vous un tutoriel sur la façon de l'inclure dans un projet iOS xCode?
james
cela vous dérangerait-il de partager comment vous avez généré la vue en utilisant quartcore? serait un grand gain de temps: P
ThomasRS
C'est vrai. Cependant, assurez-vous que vous êtes conforme à la licence du logiciel avec laquelle la bibliothèque est publiée.
GorillaPatch du
Cette question concerne la reconnaissance, pas la génération.
MonsieurDart
0

vous pouvez vérifier ZBarSDK pour lire le code QR et les codes ECN / ISBN, il est simple à intégrer essayez le code suivant.

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

}

et dans didFinishPickingMediaWithInfo, nous obtenons la valeur du code à barres.

    - (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
la source