Jak mogę skanować kody kreskowe na iOS?


189

Jak mogę po prostu zeskanować kody kreskowe na iPhonie i / lub iPadzie?


7
Niestety, aparat iPhone'a jest obecnie straszny do odczytywania kodów kreskowych, ponieważ jego obiektyw jest ustawiony na ostrość ∞. Powodzenia!
Alastair Stuart

1
Właśnie rozwiązałem ten problem, więc napiszę moje spostrzeżenia. Przetestowałem kilka opcji. RSBarcodes_Swift - był łatwy do zintegrowania, ale miał bardzo niską wydajność. ZBarSDK - był również łatwy do wdrożenia, choć kilka wyszukiwarek google szukało, jak to zrobić. Ale miał naprawdę dobrą wydajność (nie skanował datamatrix i innych rzadkich kodów) działa naprawdę dobrze dla kodów kreskowych / QRCode. Ale Scandit był najlepszy ze wszystkich. Super szybki, skanuje wszystko. niestety kosztuje sporo.
Katafalkas

Odpowiedzi:


82

Stworzyliśmy aplikację „Kody kreskowe” na iPhone'a. Może dekodować kody QR. Kod źródłowy jest dostępny z projektu zxing ; w szczególności chcesz spojrzeć na klienta iPhone'a i częściowy port C ++ biblioteki podstawowej . Port jest trochę stary, od około wersji 0.9 kodu Java, ale powinien nadal działać dość dobrze.

Jeśli chcesz przeskanować inne formaty, takie jak formaty 1D, możesz kontynuować przesyłanie kodu Java w tym projekcie do C ++.

EDYCJA: Kody kreskowe i iphonekod w projekcie zostały wycofane na początku 2014 roku.


Sean, z jakiej licencji korzysta. Chcę utworzyć płatną aplikację korzystającą z Zbar. Czy jest to możliwe na podstawie umowy licencyjnej?
Radu,

1
Żeby było jasne, czy w tej chwili ZXing na iPhonie obsługuje tylko kody QR?
RefuX

Wydaje mi się, że więcej zostało przeniesionych do C ++, ale port ten jest niestety szorstkim i przestarzałym echem kodu Java. Tak, więc obsługiwane jest więcej, choć może nie za dobrze.
Sean Owen

ZXing na iPhone'a wciąż przecieka pamięci o 1,7 ver.
Wczoraj Lee,

Z listy problemów na git zXing rozumiem, że możemy skanować kod kreskowy tylko w trybie poziomym.
Sagrian,

81

Sprawdź ZBar czyta kod QR i kody ECN / ISBN i jest dostępny jak na licencji LGPL v2.


5
Częściowo poprawne. ZBar.app jest licencjonowany na licencji Apache (wersja 2.0), jednak biblioteka jest na licencji LGPL v2.
Sean

3
Niestety licencja wymaga udostępniania plików obiektów aplikacji wszystkim, którzy o nie proszą
Ben Clayton

1
@BenClayton, co to znaczy udostępniać pliki obiektowe aplikacji?
Dejell

@Odelya Wysyłanie plików .o wygenerowanych przez Xcode każdemu, teoretycznie pozwalając im na zbudowanie Twojej aplikacji. Zdecydowanie nie jestem zadowolony z robienia tego (szczególnie dla moich klientów), więc ZBar nie wchodzi w rachubę. Strona licencjonowania ZBar sugeruje, że powinieneś po prostu „mieć nadzieję, że nikt ich nie poprosi!”
Ben Clayton

@BenClayton A. Dzięki B. Mogę zmienić komponent, jeśli ktoś zapyta i wymaga już pobranych użytkowników aplikacji, aby pobrać nowszą wersję. Wystarczy? C. Więc jakiej biblioteki używasz?
Dejell

56

Podobnie jak w przypadku wydania iOS7, nie musisz już używać zewnętrznego frameworka ani biblioteki. Ekosystem iOS z AVFoundation w pełni obsługuje skanowanie prawie każdego kodu od QR przez EAN do UPC.

Wystarczy zapoznać się z uwagą techniczną i przewodnikiem programowania AVFoundation. AVMetadataObjectTypeQRCodejest twoim przyjacielem.

Oto fajny samouczek, który pokazuje to krok po kroku: biblioteka skanów kodów QR dla iPhone'a iOS7

Mały przykład, jak to skonfigurować:

#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
Jeśli chcesz wykryć kod kreskowy z obrazu na iOS8, ten samouczek może być pomocny.
NSDeveloper

Odkryłem, że muszę zadzwonić startRunningna sesję, aby powyższy kod zadziałał na wypadek, gdyby komukolwiek to pomogło :)
Chris



10

Istnieją dwie główne biblioteki:

  • ZXing biblioteki napisanej w Javie, a następnie przeniesionej do Objective C / C ++ (tylko kod QR). Kolejny port do ObjC został zrobiony przez TheLevelUp: ZXingObjC

  • ZBar to oprogramowanie typu open source do odczytu kodów kreskowych, oparte na C.

Według moich eksperymentów ZBar jest znacznie dokładniejszy i szybszy niż ZXing, przynajmniej na iPhonie.


Wydaje mi się, że ZXingObjC to ten, który powinien zostać zepchnięty na szczyt z największą liczbą głosów. Nie używałem go jeszcze , ale opis mówi, że na równi z ZXing 2.0.
Shaolo,

Licencja ZBar wymaga od użytkowników oferowania plików obiektowych, aby mogli ją uruchomić i zmodyfikować również swoją bibliotekę.
Dejell

Polecam ZXingObjC
Dejell


7

Możesz znaleźć inne natywne rozwiązanie dla systemu iOS, używając Swift 4 i Xcode 9 poniżej. OjczystyAVFoundation środowisko używane w tym rozwiązaniu.

Pierwsza część to podklasa, z UIViewControllerktórą powiązane są funkcje konfiguracji i obsługi 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)
    }

}

Druga część to rozszerzenie naszej UIViewControllerpodklasy, w AVCaptureMetadataOutputObjectsDelegatektórej przechwytujemy przechwycone dane wyjściowe.

extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {

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

}

Aktualizacja dla Swift 4.2

.UIApplicationWillEnterForegroundzmienia się jak UIApplication.willEnterForegroundNotification.


czy to da nazwę produktu, rozmiar, cenę, adres URL produktu, walutę, nazwę sklepu? lub da tylko kod kreskowy @abdullahselek
R. Mohan

@ R.Mohan jest związany z czytanym kodem kreskowym. Sprawdź AVCaptureMetadataOutput i AVMetadataMachineReadableCodeObject i spróbuj przeczytać metadataObjectsw funkcji handleCapturedOutput .
abdullahselek

Ok, spróbuję tego. Dziękuję za odpowiedź @abdullahselek
R. Mohan

5

Nie jestem pewien, czy to pomoże, ale tutaj jest link do biblioteki kodów QR typu open source . Jak widać, kilka osób już tego używało do tworzenia aplikacji na iPhone'a.

Wikipedia ma artykuł wyjaśniający, czym są kody QR . Moim zdaniem kody QR są znacznie bardziej odpowiednie do celu niż standardowy kod kreskowy w przypadku iPhone'a, ponieważ został zaprojektowany do tego rodzaju implementacji.


5

Jeśli obsługa iPada 2 lub iPoda Touch jest ważna dla Twojej aplikacji, wybrałbym SDK skanera kodów kreskowych, który może dekodować kody kreskowe na rozmytych obrazach, taki jak nasz SDK skanera kodów kreskowych Scandit dla iOS i Androida. Dekodowanie rozmytych obrazów kodów kreskowych jest również pomocne w telefonach z aparatami z autofokusem, ponieważ użytkownik nie musi czekać na uruchomienie autofokusa.

Scandit oferuje bezpłatny plan cenowy dla społeczności, a także interfejs API produktu, który ułatwia konwersję numerów kodów kreskowych na nazwy produktów.

(Uwaga: Jestem współzałożycielem Scandit)


4

Jakie masz wrażenia z korzystania z tej aplikacji? Dla mnie dekodowanie prostego kodu kreskowego z datamatrix zajmuje 10 s lub więcej!
iamj4de


1
Bezpośredni link (nie sądzę, że Google na jakiś czas to zniknie) code.google.com/p/barcodeapp

czy ktoś wie, jaka jest oficjalna nazwa aplikacji Stefana w sklepie z aplikacjami? Chciałbym go pobrać przed zanurzeniem się w kod.
macutan

3

Problem z aparatem iPhone'a polega na tym, że pierwsze modele (których używa się ton) mają aparat o stałej ogniskowej, który nie może wykonać zdjęcia z odległości do 2 stóp. Obrazy są rozmyte i zniekształcone, a jeśli są robione z większej odległości, nie ma wystarczającej ilości szczegółów / informacji z kodu kreskowego.

Kilka firm opracowało aplikacje na iPhone'a, które mogą sobie na to pozwolić, wykorzystując zaawansowane technologie usuwania rozmazań. Aplikacje, które można znaleźć w Apple App Store: pic2shop, RedLaser i ShopSavvy. Wszystkie firmy ogłosiły, że mają również dostępne zestawy SDK - niektóre za darmo lub bardzo preferencyjne warunki, sprawdź jedno z nich.


Próbowałem użyć ShopSavvy z iPhone'em 3G. To zabawne, ale bardzo często ulega awarii i bardzo, bardzo trudno jest odczytać bardzo wyraźne, płaskie kody kreskowe.
James Moore,

1
Właśnie próbowałem pic2shop. Cytat od mojej narzeczonej: „To ma ułatwić nam życie JAK?” To urocza aplikacja, ale o ile wiem, nie jest w stanie odczytać kodu kreskowego.
James Moore,

Który format próbowałeś przeczytać? Próbowałem użyć pic2shop do skanowania EAN i działa bardzo dobrze. Opłata licencyjna jest jednak droga, nawet większa niż RedLaser.
iamj4de

2

z Swift 5 jest to proste i super szybkie !!

Wystarczy dodać strąki kakaowe „BarcodeScanner” tutaj jest pełny kod

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

Upewnij się, że dodajesz uprawnienia aparatu do pliku .plist

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

I w ten sposób dodaj skaner i obsłuż wynik w swoim 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)
    }
}

Nadal i wszelkie pytania lub wyzwania, sprawdź tutaj przykładową aplikację z pełnym kodem źródłowym



1

Wierzę, że można to zrobić za pomocą AVFramework, oto przykładowy kod, aby to zrobić

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

Oto prosty kod:

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

Jeśli tworzysz dla iOS> 10.2 z Swift 4, możesz wypróbować moje rozwiązanie. I miesza się ten i ten samouczek i wymyślił ViewController który skanuje kod QR, i print()ją. Mam również przełącznik w interfejsie użytkownika, aby przełączać światło kamery, może być również pomocne. Na razie testowałem go tylko na iPhone SE, daj mi znać, jeśli nie działa na nowszych iPhone'ach.

Proszę bardzo:

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

Czasami przydatne może być również generowanie kodów QR . Jest do tego znakomita biblioteka C, która działa jak urok. Nazywa się to libqrencode . Pisanie niestandardowego widoku do wyświetlania kodu QR nie jest więc trudne i można to zrobić przy podstawowym zrozumieniu QuartzCore.


czy znasz jakiś samouczek na temat włączenia tego do projektu xCode systemu iOS?
James

czy mógłbyś podzielić się tym, jak wygenerowałeś widok za pomocą quartcore? zaoszczędziłbym dużo czasu: P
ThomasRS

Zgadza się. Jednak upewnij się, że jesteś zgodny z licencją na oprogramowanie, biblioteka została opublikowana.
GorillaPatch

To pytanie dotyczy uznania, a nie generacji.
MonsieurDart

0

możesz sprawdzić ZBarSDK, aby odczytać kod QR, a kody ECN / ISBN można łatwo zintegrować, wypróbuj następujący kod.

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

}

aw didFinishPickingMediaWithInfo otrzymujemy wartość kodu kreskowego.

    - (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];
   }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.