How to scan for QR codes on button press?

冷暖自知 提交于 2019-12-11 12:13:52

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!