Wie kann ich Barcodes unter iOS scannen?


189

Wie kann ich einfach Barcodes auf iPhone und / oder iPad scannen?


7
Leider ist die iPhone-Kamera derzeit für das Lesen von Barcodes schrecklich, da das Objektiv auf ∞ eingestellt ist. Viel Glück!
Alastair Stuart

1
Ich habe gerade dieses Problem gelöst und werde meine Beobachtungen schreiben. Ich habe einige Optionen getestet. RSBarcodes_Swift - war einfach zu integrieren, hatte aber eine sehr schlechte Leistung. ZBarSDK - war auch einfach zu implementieren, obwohl nur wenige Google-Suchanfragen durchgeführt wurden, um herauszufinden, wie. Hatte aber wirklich gute Leistung (Datamatrix und andere seltene Codes nicht gescannt) funktioniert wirklich gut für Barcodes / QRCode. Aber Scandit war der beste von allen. Super schnell, scannt alles. kostet leider ziemlich viel.
Katafalkas

Antworten:


82

Wir haben die 'Barcodes'-Anwendung für das iPhone erstellt. Es kann QR-Codes dekodieren. Der Quellcode ist im zxing-Projekt verfügbar . Insbesondere möchten Sie einen Blick auf den iPhone-Client und den partiellen C ++ - Port der Kernbibliothek werfen . Der Port ist etwas alt, ab ca. Version 0.9 des Java-Codes, sollte aber trotzdem einigermaßen gut funktionieren.

Wenn Sie andere Formate wie 1D-Formate scannen müssen, können Sie den Port des Java-Codes in diesem Projekt nach C ++ fortsetzen.

BEARBEITEN: Barcodes und der iphoneCode im Projekt wurden Anfang 2014 eingestellt.


Sean, welche Art von Lizenz wird verwendet? Ich möchte eine kostenpflichtige App erstellen, die Zbar verwendet. Ist das im Rahmen der Lizenzvereinbarung möglich?
Radu

1
Um ganz klar zu sein, unterstützt ZXing auf dem iPhone zu diesem Zeitpunkt nur QR-Codes?
RefuX

Ich glaube, es wurde mehr nach C ++ portiert, aber der Port ist leider immer noch ein grobes und veraltetes Echo des Java-Codes. Also ja ja mehr wird aber vielleicht nicht gut unterstützt.
Sean Owen

ZXing für iPhone hat immer noch Speicherlecks von 1,7 ver.
Yoon Lee

Ich verstehe aus der Problemliste auf git von zXing, dass wir Barcode nur im Querformat scannen können.
Sagrian

81

Check out ZBar liest QR-Code und ECN / ISBN-Codes und ist unter der LGPL v2-Lizenz erhältlich.


5
Teilweise richtig. Die ZBar.app ist unter der Apache-Lizenz (Version 2.0) lizenziert , die Bibliothek ist jedoch unter der LGPL v2 lizenziert.
Sean

3
Leider erfordert die Lizenz, dass Sie die Objektdateien Ihrer App für jeden freigeben
Ben Clayton

1
@ BenClayton Was bedeutet es, die Objektdateien der App freizugeben?
Dejell

@Odelya Senden der von Xcode generierten .o-Dateien an jeden, damit diese theoretisch Ihre App erstellen können. Ich bin definitiv nicht glücklich darüber (besonders für meine Kunden), daher kommt ZBar für uns nicht in Frage. Auf der ZBar-Lizenzierungsseite wird empfohlen, nur zu hoffen, dass niemand sie anfordert.
Ben Clayton

@ BenClayton A. Danke B. Ich könnte die Komponente ändern, wenn jemand die bereits heruntergeladenen App-Benutzer auffordert und verlangt, eine neuere Version herunterzuladen. Reicht das? C. Welche Bibliothek verwenden Sie?
Dejell

56

Wie bei der Veröffentlichung müssen iOS7Sie kein externes Framework oder keine externe Bibliothek mehr verwenden. Das iOS-Ökosystem mit AVFoundation unterstützt jetzt das Scannen vollständig fast aller Codes von QR über EAN bis UPC.

Schauen Sie sich einfach den Tech Note und die AVFoundation-Programmieranleitung an. AVMetadataObjectTypeQRCodeist dein Freund.

Hier ist ein schönes Tutorial, das es Schritt für Schritt zeigt: iPhone QR Code Scan Bibliothek iOS7

Nur ein kleines Beispiel für die Einrichtung:

#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
Wenn Sie unter iOS8 einen Barcode aus dem Bild erkennen möchten, kann dieses Tutorial hilfreich sein.
NSDeveloper

Ich fand, ich musste startRunningdie Sitzung anrufen , damit der obige Code funktioniert, falls das jemandem hilft :)
Chris

13

Die iPhone 4-Kamera ist mehr als nur eine Möglichkeit, Barcodes zu erstellen. Die Barcode-Bibliothek für Zebrastreifen hat eine Gabel auf dem Github ZXING-iPhone . Es ist Open Source.


1
Ihr Beitrag scheint zu implizieren, dass dieser Port von ZXing mehr als nur QRCodes scannen kann? Ist das der Fall?
RefuX

4
Die Github-Gabel scheint tot zu sein, wie in diesem Problem angegeben: github.com/joelind/zxing-iphone/issues/3
Josh Brown

10

liteqr ist ein "Lite QR Reader in Objective C, portiert von zxing" auf Github und unterstützt Xcode 4.


10

Es gibt zwei Hauptbibliotheken:

  • ZXen einer in Java geschriebenen und dann auf Objective C / C ++ portierten Bibliothek (nur QR-Code). Und ein anderer Port zu ObjC wurde von TheLevelUp durchgeführt: ZXingObjC

  • ZBar ist eine Open-Source-Software zum Lesen von Barcodes auf C-Basis.

Nach meinen Experimenten ist ZBar viel genauer und schneller als ZXing, zumindest auf dem iPhone.


Mir scheint, ZXingObjC ist derjenige, der jetzt mit den meisten Stimmen an die Spitze gedrängt werden sollte. Ich habe es noch nicht verwendet , aber die Beschreibung besagt, dass es mit ZXing 2.0 übereinstimmt.
Shaolo

Für die ZBar-Lizenz müssen Sie den Benutzern die Objektdateien anbieten, damit sie sie ausführen und auch ihre Bibliothek ändern können.
Dejell

Ich empfehle ZXingObjC
Dejell


7

Eine weitere native iOS-Lösung mit Swift 4 und Xcode 9 finden Sie unten. Natives AVFoundationFramework, das in dieser Lösung verwendet wird.

Der erste Teil ist eine Unterklasse, für UIViewControllerdie entsprechende Setup- und Handlerfunktionen vorhanden sind 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)
    }

}

Der zweite Teil ist die Erweiterung unserer UIViewControllerUnterklasse, AVCaptureMetadataOutputObjectsDelegatein der wir die erfassten Ausgaben erfassen.

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Update für Swift 4.2

.UIApplicationWillEnterForegroundändert sich als UIApplication.willEnterForegroundNotification.


Gibt dies den Produktnamen, die Größe, den Preis, die Produkt-URL, die Währung und den Benutzernamen an? oder es wird nur die Barcode-Nummer @abdullahselek
R. Mohan

@ R.Mohan es hängt mit dem Barcode zusammen, den Sie gelesen haben. Bitte überprüfen Sie AVCaptureMetadataOutput und AVMetadataMachineReadableCodeObject und versuchen , das Lesen metadataObjectsin der handleCapturedOutput Funktion.
Abdullahselek

Ok, werde das versuchen. Vielen Dank für die Antwort @abdullahselek
R. Mohan

5

Ich bin mir nicht sicher, ob dies helfen wird, aber hier ist ein Link zu einer Open-Source- QR-Code-Bibliothek . Wie Sie sehen, haben einige Leute dies bereits verwendet, um Apps für das iPhone zu erstellen.

Wikipedia hat einen Artikel, der erklärt, was QR-Codes sind . Meiner Meinung nach sind QR-Codes viel zweckmäßiger als der Standard-Barcode, wenn es um das iPhone geht, da es für diese Art der Implementierung entwickelt wurde.


5

Wenn die Unterstützung für das iPad 2 oder den iPod Touch für Ihre Anwendung wichtig ist, würde ich ein Barcode-Scanner-SDK wählen, das Barcodes in verschwommenen Bildern dekodieren kann, wie z. B. unser Scandit-Barcode-Scanner-SDK für iOS und Android. Das Dekodieren verschwommener Barcode-Bilder ist auch bei Telefonen mit Autofokus-Kameras hilfreich, da der Benutzer nicht warten muss, bis der Autofokus aktiviert wird.

Scandit wird mit einem kostenlosen Community-Preisplan geliefert und verfügt über eine Produkt-API, mit der Barcode-Nummern einfach in Produktnamen umgewandelt werden können.

(Haftungsausschluss: Ich bin Mitbegründer von Scandit)


4

Sie können sich den iPhone DataMatrix Reader-Quellcode von Stefan Hafeneger ( Google Code-Projekt ; archivierter Blog-Beitrag ) ansehen, falls dieser noch verfügbar ist.


Wie ist deine Erfahrung mit dieser App? Für mich dauert es 10s oder länger, um einen einfachen Datamatrix-Barcode zu dekodieren!
iamj4de


1
Direkter Link (ich glaube nicht, dass Google dies für eine Weile verschwinden lässt) code.google.com/p/barcodeapp

Weiß jemand, wie der offizielle Name von Stefans App im Appstore lautet? Ich möchte es herunterladen, bevor ich in den eigentlichen Code eintauche.
Macutan

3

Das Problem mit der iPhone-Kamera ist, dass die ersten Modelle (von denen Tonnen verwendet werden) über eine Kamera mit festem Fokus verfügen, die bei Entfernungen unter 2 Fuß kein scharfes Bild aufnehmen kann. Die Bilder sind verschwommen und verzerrt, und wenn sie aus größerer Entfernung aufgenommen werden, enthält der Barcode nicht genügend Details / Informationen.

Einige Unternehmen haben iPhone-Apps entwickelt, die dies mithilfe fortschrittlicher Entschärfungstechnologien berücksichtigen können. Diese Anwendungen finden Sie im Apple App Store: pic2shop, RedLaser und ShopSavvy. Alle Unternehmen haben angekündigt, dass sie auch SDKs zur Verfügung haben - einige kostenlos oder zu sehr günstigen Konditionen.


Ich habe versucht, ShopSavvy mit einem 3G-iPhone zu verwenden. Es ist amüsant, stürzt aber sehr häufig ab und hat es sehr, sehr schwer, sehr klare, flache Barcodes zu lesen.
James Moore

1
Und ich habe gerade pic2shop ausprobiert. Zitat meiner Verlobten: "Das soll unser Leben leichter machen, WIE?" Es ist eine niedliche App, aber soweit ich das beurteilen kann, kann sie keinen Barcode lesen.
James Moore

Welches Format haben Sie versucht zu lesen? Ich habe versucht, mit pic2shop EAN zu scannen, und es funktioniert sehr gut. Die Lizenzgebühr ist jedoch teurer als RedLaser.
iamj4de

2

mit Swift 5 ist es einfach und super schnell !!

Sie müssen nur Kakaofrüchte "BarcodeScanner" hinzufügen, hier ist der vollständige Code

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

Stellen Sie sicher, dass Sie in Ihrer .plist-Datei die Berechtigung Kamera hinzufügen

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

Fügen Sie auf diese Weise den Scanner hinzu und verarbeiten Sie das Ergebnis in Ihrem ViewController

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

Bei Fragen oder Herausforderungen überprüfen Sie bitte die Beispielanwendung hier mit dem vollständigen Quellcode



1

Ich glaube, dass dies mit AVFramework möglich ist. Hier ist der Beispielcode dafür

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

Hier ist einfacher Code:

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

Wenn Sie mit Swift 4 für iOS> 10.2 entwickeln, können Sie meine Lösung ausprobieren. Ich habe dieses und dieses Tutorial verwechselt und mir einen ViewController ausgedacht, der einen QR-Code scannt und print()herausfindet. Ich habe auch einen Schalter in meiner Benutzeroberfläche, um das Kameralicht umzuschalten. Dies könnte ebenfalls hilfreich sein. Im Moment habe ich es nur auf einem iPhone SE getestet. Bitte lassen Sie mich wissen, wenn es auf neueren iPhones nicht funktioniert.

Bitte schön:

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

Manchmal kann es auch nützlich sein, QR-Codes zu generieren . Dafür gibt es eine hervorragende C-Bibliothek, die wie ein Zauber wirkt. Es heißt libqrencode . Das Schreiben einer benutzerdefinierten Ansicht zum Anzeigen des QR-Codes ist dann nicht so schwierig und kann mit einem grundlegenden Verständnis von QuartzCore durchgeführt werden.


Kennen Sie ein Tutorial, wie Sie dies in ein iOS xCode-Projekt aufnehmen können?
James

Würde es Ihnen etwas ausmachen, mitzuteilen, wie Sie die Ansicht mit Quartcore generiert haben? wäre eine große Zeitersparnis: P
ThomasRS

Das ist richtig. Stellen Sie jedoch sicher, dass Sie mit der Softwarelizenz kompatibel sind, mit der die Bibliothek veröffentlicht wird.
GorillaPatch

Bei dieser Frage geht es um Anerkennung, nicht um Generation.
MonsieurDart

0

Sie können ZBarSDK überprüfen, um QR-Code und ECN / ISBN-Codes zu lesen. Es ist einfach zu integrieren. Versuchen Sie den folgenden Code.

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

}

und in didFinishPickingMediaWithInfo erhalten wir einen Barcode-Wert.

    - (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];
   }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.