Je suis ceci tutoriel et j'ai essayé de convertir les codes sous forme Swift 2.0 à 3.0. Mais quand j'ai lancé l'application, l'application ne fonctionne pas! Je veux dire, rien ne se passe! Voici mon code:
ViewController:
class ViewController: UIViewController ,BarcodeDelegate {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let barcodeViewController: BarcodeViewController = segue.destination as! BarcodeViewController
barcodeViewController.delegate = self
}
func barcodeReaded(barcode: String) {
codeTextView.text = barcode
print(barcode)
}
}
BarcodeVC:
import AVFoundation
protocol BarcodeDelegate {
func barcodeReaded(barcode: String)
}
class BarcodeViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegate {
var delegate: BarcodeDelegate?
var captureSession: AVCaptureSession!
var code: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("works")
self.captureSession = AVCaptureSession();
let videoCaptureDevice: AVCaptureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
let videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
if self.captureSession.canAddInput(videoInput) {
self.captureSession.addInput(videoInput)
} else {
print("Could not add video input")
}
let metadataOutput = AVCaptureMetadataOutput()
if self.captureSession.canAddOutput(metadataOutput) {
self.captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code]
} else {
print("Could not add metadata output")
}
let previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
previewLayer?.frame = self.view.layer.bounds
self.view.layer .addSublayer(previewLayer!)
self.captureSession.startRunning()
} catch let error as NSError {
print("Error while creating vide input device: \(error.localizedDescription)")
}
}
//I THINK THIS METHOD NOT CALL !
private func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
// This is the delegate'smethod that is called when a code is readed
for metadata in metadataObjects {
let readableObject = metadata as! AVMetadataMachineReadableCodeObject
let code = readableObject.stringValue
// If the code is not empty the code is ready and we call out delegate to pass the code.
if code!.isEmpty {
print("is empty")
}else {
self.captureSession.stopRunning()
self.dismiss(animated: true, completion: nil)
self.delegate?.barcodeReaded(barcode: code!)
}
}
}
Voici la sortie:
2016-09-17 18: 10: 26.000919 BarcodeScaning [2610: 674253] [MC] Le conteneur du groupe système pour systemgroup.com.Apple.configurationprofiles est/private/var/containers/Shared/SystemGroup/systemgroup.com.Apple.configurationprofiles 2016-09-17 18: 10: 26.007782 BarcodeScaning [2610: 674253] [MC] Lecture à partir des paramètres utilisateur effectifs publics.
Voici réponse de Victor Sigler mise à jour vers Swift 4 sans déballage forcé, un protocole faible, exécutant du code coûteux dans le thread d'arrière-plan et autres raffinements.
Notez que la méthode de AVCaptureMetadataOutputObjectsDelegate
est passée de
captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!)
à
metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection)
import UIKit
import AVFoundation
protocol BarcodeDelegate: class {
func barcodeRead(barcode: String)
}
class ScannerViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
weak var delegate: BarcodeDelegate?
var output = AVCaptureMetadataOutput()
var previewLayer: AVCaptureVideoPreviewLayer!
var captureSession = AVCaptureSession()
override func viewDidLoad() {
super.viewDidLoad()
setupCamera()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.global(qos: .background).async {
if !self.captureSession.isRunning {
self.captureSession.startRunning()
}
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
DispatchQueue.global(qos: .background).async {
if self.captureSession.isRunning {
self.captureSession.stopRunning()
}
}
}
fileprivate func setupCamera() {
guard let device = AVCaptureDevice.default(for: .video),
let input = try? AVCaptureDeviceInput(device: device) else {
return
}
DispatchQueue.global(qos: .background).async {
if self.captureSession.canAddInput(input) {
self.captureSession.addInput(input)
}
let metadataOutput = AVCaptureMetadataOutput()
if self.captureSession.canAddOutput(metadataOutput) {
self.captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: .global(qos: .background))
if Set([.qr, .ean13]).isSubset(of: metadataOutput.availableMetadataObjectTypes) {
metadataOutput.metadataObjectTypes = [.qr, .ean13]
}
} else {
print("Could not add metadata output")
}
self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
self.previewLayer.videoGravity = .resizeAspectFill
DispatchQueue.main.async {
self.previewLayer.frame = self.view.bounds
self.view.layer.addSublayer(self.previewLayer)
}
}
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
// This is the delegate's method that is called when a code is read
for metadata in metadataObjects {
if let readableObject = metadata as? AVMetadataMachineReadableCodeObject,
let code = readableObject.stringValue {
dismiss(animated: true)
delegate?.barcodeRead(barcode: code)
print(code)
}
}
}
}
Ci-dessous, je voudrais partager avec quelques idées en fonction de la numérisation de codes à barres dans iOS.
exposurePointOfInterest
et focusPointOfInterest
rectOfInterests
avec CGRect converti appropriéfocusMode
et exposureMode
lockForConfiguration
correctement tout en modifiant les paramètres de capture de la caméra Ajouter une entrée dans le fichier .plist
Dans le fichier Info.plist, ajoutez le code suivant pour permettre à votre application d'accéder à la caméra de l'iPhone:
<key>NSCameraUsageDescription</key>
<string>Allow access to camera</string>
Définir expositionPointOfInterest et focusPointOfInterest exposurePointOfInterest
et focusPointOfInterest
permettent une meilleure qualité de numérisation, une mise au point plus rapide de la caméra sur le point central de l'écran.
Définir rectOfInterests
Cette propriété permet à la caméra de se concentrer uniquement sur une partie de l'écran. De cette façon, le code peut être scanné plus rapidement, concentré uniquement sur les codes présentés au centre de l'écran - ce qui est utile alors que peu d'autres codes sont disponibles en arrière-plan.
Définir focusMode et expositionMode Les propriétés doivent être définies comme suit:
device.focusMode = .continuousAutoFocus
device.exposureMode = .continuousAutoExposure
Cela permet de se concentrer en continu et de régler l'exposition bien ajustée au code de numérisation.
Ici vous pouvez trouver un projet prêt à mettre en œuvre cette idée: https://github.com/lukszar/QuickScanner
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
print("caught QR code")
for metadata in metadataObjects {
let readableObject = metadata as! AVMetadataMachineReadableCodeObject
let code = readableObject.stringValue
if code!.isEmpty {
print("is empty")
} else {
self.captureSession.stopRunning()
self.dismiss(animated: true, completion: nil)
self.delegate?.gotQRCode(code: code!)
}
}
}
On dirait que la signature de la méthode a changé un peu dans Swift 3. Voici la version correcte
Vous devez ajouter NSCameraUsageDescription à votre fichier Info.plist pour le faire fonctionner!
Ajoutez simplement une ligne dans info.plist et tapez NSCameraUsageDescription dans la ligne nouvellement créée et ajoutez une chaîne destinée à informer l'utilisateur des raisons pour lesquelles l'accès à la caméra est nécessaire dans votre application.
Cela devrait faire l'affaire!