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 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.
@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.
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.
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.
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.
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
classBarCodeScannerViewController: UIViewController{
let captureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer!var initialized = falselet 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]
overridefuncviewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupCapture()
// set observer for UIApplicationWillEnterForeground, so we know when to start the capture session againNotificationCenter.default.addObserver(self,
selector: #selector(willEnterForeground),
name: .UIApplicationWillEnterForeground,
object: nil)
}
overridefuncviewWillDisappear(_ 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@objcfuncwillEnterForeground() {
setupCapture()
}
funcsetupCapture() {
var success = falsevar accessDenied = falsevar accessRequested = falselet authorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
if authorizationStatus == .notDetermined {
// permission dialog not yet presented, request authorization
accessRequested = trueAVCaptureDevice.requestAccess(for: .video,
completionHandler: { (granted:Bool) -> Voidinself.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)
iflet captureDevice = deviceDiscoverySession.devices.first {
do {
let videoInput = tryAVCaptureDeviceInput(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 userif !accessRequested {
// Generic message if we cannot figure out why we cannot establish a camera sessionvar 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) -> Voidinself.navigationController?.popViewController(animated: true)
})
alertPrompt.addAction(confirmAction)
self.present(alertPrompt, animated: true, completion: nil)
}
}
}
funchandleCapturedOutput(metadataObjects: [AVMetadataObject]) {
if metadataObjects.count == 0 {
return
}
guardlet metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObjectelse {
return
}
if barCodeTypes.contains(metadataObject.type) {
iflet metaDataString = metadataObject.stringValue {
captureSession.stopRunning()
displayResult(code: metaDataString)
return
}
}
}
funcdisplayResult(code: String) {
let alertPrompt = UIAlertController(title: "Bar code detected", message: code, preferredStyle: .alert)
iflet url = URL(string: code) {
let confirmAction = UIAlertAction(title: "Launch URL", style: .default, handler: { (action) -> VoidinUIApplication.shared.open(url, options: [:], completionHandler: { (result) inif 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) -> Voidin
})
alertPrompt.addAction(confirmAction)
self.present(alertPrompt, animated: true, completion: {
self.setupCapture()
})
}
})
})
alertPrompt.addAction(confirmAction)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Voidinself.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.
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
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.
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.
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à.
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 'SimpleBarcodeScanner'do
pod 'BarcodeScanner'
end
Assurez-vous d'ajouter l'autorisation de la caméra dans votre fichier .plist
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
classQRCodeScanner: UIViewController, AVCaptureMetadataOutputObjectsDelegate{
let captureSession: AVCaptureSession = AVCaptureSession()
var videoPreviewLayer: AVCaptureVideoPreviewLayer?let qrCodeFrameView: UIView = UIView()
var captureDevice: AVCaptureDevice?overridefuncviewDidLoad() {
// Get the back-facing camera for capturing videoslet 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 = tryAVCaptureDeviceInput(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)
iflet videoPreviewLayer = videoPreviewLayer {
videoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer)
// Start video capture.
captureSession.startRunning()
iflet 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@IBActionfuncswitchFlashChanged(_ sender: UISwitch) {
do {
if sender.isOn {
captureDevice?.torchMode = .on
} else {
captureDevice?.torchMode = .off
}
}
}
// MARK: AVCaptureMetadataOutputObjectsDelegatefuncmetadataOutput(_ 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! AVMetadataMachineReadableCodeObjectif 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 boundslet barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView.frame = barCodeObject!.bounds
print("QR Code: \(metadataObj.stringValue)")
}
}
}
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.
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 feedZBarReaderViewController *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 barcodebreak;
// 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];
}
Réponses:
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
iphone
code du projet ont été supprimés vers le début de 2014.la source
Vérifiez que ZBar lit le code QR et les codes ECN / ISBN et est disponible sous la licence LGPL v2.
la source
Comme avec la sortie,
iOS7
vous 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.
AVMetadataObjectTypeQRCode
est 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]; }
la source
startRunning
la session pour que le code ci-dessus fonctionne au cas où cela aiderait quelqu'un :)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.
la source
liteqr est un "Lite QR Reader en Objective C porté depuis zxing" sur github et prend en charge Xcode 4.
la source
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.
la source
HOWTO: Ajouter un lecteur de code-barres à une application iPhone , qui pointe vers ZBar iPhone SDK , semble utile (à partir d'un autre fil ).
la source
Vous pouvez trouver une autre solution iOS native utilisant Swift 4 et Xcode 9 ci-dessous.
AVFoundation
Framework natif utilisé dans cette solution.La première partie est une sous-classe
UIViewController
dont les fonctions de configuration et de gestion sont associéesAVCaptureSession
.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
UIViewController
sous-classeAVCaptureMetadataOutputObjectsDelegate
où 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
.UIApplicationWillEnterForeground
change commeUIApplication.willEnterForegroundNotification
.la source
metadataObjects
à l'intérieur du handleCapturedOutput fonction .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.
la source
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)
la source
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.
la source
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à.
la source
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
la source
Pour un scanner de code-barres natif iOS 7, jetez un œil à mon projet sur GitHub:
la source
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 } } } }
la source
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 }
la source
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)") } } }
la source
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.
la source
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]; }
la source