Como posso digitalizar códigos de barras nos iOS?
11 answers
Se precisar de digitalizar outros formatos, como os formatos 1D, poderá continuar o porto do código Java dentro deste projecto para C++.
Editar: os códigos de barras e o código iphone
do projecto foram retirados no início de 2014.
Check out ZBar reads QR Code and ECN / ISBN codes and is available as under the LGPL v2 license.
Tal como acontece com o lançamento de iOS7
já não precisa de usar uma estrutura ou biblioteca externa. O ecossistema iOS com base em AVFoundation suporta agora totalmente a digitalização {[[6]} de quase todos os códigos desde QR até EAN até UPC.
Dá uma vista de olhos na nota técnica e no Guia de programação AVFoundation. É teu amigo.
Aqui está um bom tutorial {[[5]}que o mostra passo a passo: iPhone QR code scan library iOS7
Apenas um pequeno exemplo de como prepara-o.#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];
}
A câmara do iPhone 4 é mais do que capabale de fazer códigos de barras. A biblioteca do código de barras Zebra tem um garfo no github zxing-iphone . É de código aberto.
Liteqr é um leitor de "Lite QR em Objetivo C portado a partir de zxing" no github e tem suporte para Xcode 4.
ZXing uma biblioteca escrita em Java e depois portada para o Objectivo C / C++ (apenas o código QR). E um outro porto para ObjC foi feito, pela elevação: ZXingObjC
ZBar um software de código aberto para leitura de códigos de barras, baseado em C.
De acordo com as minhas experiências, O ZBar é muito mais preciso e rápido do que o ZXing, pelo menos no iPhone.
HOWTO: adicione um leitor de código de barras a um aplicativo de iPhone, que aponta para ZBar iPhone SDK, parece útil (de outro tópico).
Não tenho a certeza se isto irá ajudar, mas aqui está um link para uma biblioteca de código QR . Como você pode ver, algumas pessoas já usaram isso para criar aplicativos para o iphone.
A Wikipédia tem um artigo a explicar Quais são os códigos QR . Na minha opinião, os códigos QR são muito mais adequados para a finalidade do que o código de barras padrão no que diz respeito ao iphone, uma vez que foi projetado para este tipo de implementação.
Se o suporte para o iPad 2 ou iPod Touch for importante para a sua aplicação, eu escolheria um Scanner SDK de código de barras que pode descodificar códigos de barras em imagens desfocadas, como o nosso Scandit Scanner SDK para iOS e Android. Descodificar imagens de código de barras borrado também é útil em telefones com câmeras autofocus porque o Usuário não tem que esperar que o autofocus faça efeito.
[[1]}Scandit vem com um plano de preços comunitário gratuito e também tem uma API de produto que torna fácil de converter números de código de barras em nomes de produtos.(Disclaimer: i'm a co-founder of Scandit)
Podias dar uma vista de olhos ao iPhone DataMatrix do Stefan Hafeneger. ( projecto de código Google; post arquivado no blog ) se ainda estiver disponível.
Você pode encontrar outra solução nativa iOS usando Swift 4 e Xcode 9 em baixo. Native AVFoundation
framework usado nesta solução.
A primeira parte é a subclasse a de UIViewController
que têm funções relacionadas de configuração e tratamento para 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)
}
}
A segunda parte é a extensão da nossa subclasse UIViewController
para AVCaptureMetadataOutputObjectsDelegate
onde apanhamos as saídas capturadas.
extension BarCodeScannerViewController: AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
handleCapturedOutput(metadataObjects: metadataObjects)
}
}
Actualização para o Swift 4.2
.UIApplicationWillEnterForeground
alterações em UIApplication.willEnterForegroundNotification
.