问题
I am using the code provided by https://www.hackingwithswift.com/example-code/media/how-to-scan-a-qr-code to make my own scanning app. But I like my scanning to occur on button press. Now for this I put the viewDidLoad()
part from the tutorial into its own function:
func cameraScanningLayer(){
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())
// need to scan barcode + QRcode
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeCode39Code]
} else {
failed()
return
}
// Previewlayer with camera
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession);
previewLayer.frame = viewForLayer.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
viewForLayer.layer.addSublayer(previewLayer);
captureSession.startRunning();
}
And a button action calls the function:
func buttonScanAction() {
print("Scan")
scanEnabled = true // like to use some kind of bool/switch
self.cameraScanningLayer()
}
The problems I have are:
1) On load the camera is not in view
2) After the button is pressed the camera is in view but it always scans automatically
So I thought of using a global:
var scanEnabled: Bool = false
Then, when the button is clicked, set it to true and the scanning is enabled.
For reference here is a sketch:
EDIT my quick fix which might not be the right way to do it.
I replaced the
let metadataOutput = AVCaptureMetadataOutput() {...} else {
failed()
return
}
and put it between an if statement
if (scanEnabled == true) {
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
// to use them both wwe need to skip AVMetadataObjectTypeQRCode
metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeCode39Code]
scanEnabled = false
} else {
failed()
return
}
}
回答1:
Author of that tutorial here. My method was to use a dedicated scanning view controller, but I guess you want to unify that with your existing view controller – and that's fine. Both approaches work.
If you want to show the camera interface all the time (even when not actively recognising QR codes) then your plan to use a boolean to track whether scanning is enabled is a good one. My example code has a foundCode()
method that gets called, and also calls dismissViewControllerAnimated()
when codes are found.
In your version, you need to make foundCode()
do all the work of stopping the scane, handling the dismissal, etc. You can then add a check for your scanEnabled
boolean in one place.
Something like this ought to do it:
func foundCode(code: String) {
if scanCode == true {
print(code)
captureSession.stopRunning()
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
dismissViewControllerAnimated(true, completion: nil)
}
}
If you wanted to, you could move the scanCode == true
check up to didOutputMetadataObjects
to save the unnecessary method call.
来源:https://stackoverflow.com/questions/34291010/how-to-scan-for-qr-codes-on-button-press