Search code examples
iosswiftxcodeqr-codebarcode

QRCodereader extra buttons not working (torchlight/flashlight, cancel, switchcamera)?


I've implemented the example app from (https://cocoapods.org/pods/QRCodeReader.swift) to my own project to make a uiview on my main screen that displays a barcode scanner. I can scan a barcode and print the result, but the torchlight (flashlight) button does nothing when pressed, same with cancel and switchcamerabutton, even though the icons are displayed on the view. What could be the problem?

This is my code:

import UIKit
import QRCodeReader

class Plockning: UIViewController {

    lazy var reader: QRCodeReader = QRCodeReader(metadataObjectTypes: [.ean13, .upce, .code128], captureDevicePosition: .back)

    @IBOutlet weak var Uiview: QRCodeReaderView! {
        didSet {
          Uiview.setupComponents(with: QRCodeReaderViewControllerBuilder {
            $0.reader                 = reader
            $0.showTorchButton        = true // ICON SHOWS ON VIEW BUT PRESSING ON IT DOES NOTHING.
            $0.showSwitchCameraButton = true // ICON SHOWS ON VIEW BUT PRESSING ON IT DOES NOTHING.
            $0.showCancelButton       = true // ICON SHOWS ON VIEW BUT PRESSING ON IT DOES NOTHING.
            $0.showOverlayView        = true // THIS DOESN'T SHOW ON SCREEN
            $0.rectOfInterest         = CGRect(x: 0.2, y: 0.2, width: 0.6, height: 0.6)
          })
        }
      }




    override func viewDidLoad()
    {
        super.viewDidLoad()


        reader.startScanning()

        reader.didFindCode = { result in
          print("Completion with result: (result.value) of type (result.metadataType)")
        }
    }

}

Solution

  • You need to examine the source code more fully.

    This line, for example:

    .showTorchButton = true
    

    adds a "default" toggleTorchButton to the interface, but that button doesn't do anything until you tell it what you want it to do.

    In the supplied QRCodeReaderViewController, we find this line:

    builder.readerView.displayable.toggleTorchButton?.addTarget(self, action: #selector(toggleTorchAction), for: .touchUpInside)
    

    and the corresponding selector:

    @objc func toggleTorchAction(_ button: ToggleTorchButton) {
        codeReader.toggleTorch()
    }
    

    So, for your app, you would implement the same selector func, and add the action to the QRCodeReaderView you've setup:

    class Plockning: UIViewController {
        
        lazy var reader: QRCodeReader = QRCodeReader(metadataObjectTypes: [.ean13, .upce, .code128], captureDevicePosition: .back)
        
        @IBOutlet weak var Uiview: QRCodeReaderView! {
            didSet {
                Uiview.setupComponents(with: QRCodeReaderViewControllerBuilder {
                    $0.reader                 = reader
                    $0.showTorchButton        = true // ICON SHOWS ON VIEW BUT PRESSING ON IT DOES NOTHING.
                    $0.showSwitchCameraButton = true // ICON SHOWS ON VIEW BUT PRESSING ON IT DOES NOTHING.
                    $0.showCancelButton       = true // ICON SHOWS ON VIEW BUT PRESSING ON IT DOES NOTHING.
                    $0.showOverlayView        = true // THIS DOESN'T SHOW ON SCREEN
                    $0.rectOfInterest         = CGRect(x: 0.2, y: 0.2, width: 0.6, height: 0.6)
                })
            }
        }
        
        override func viewDidLoad()
        {
            super.viewDidLoad()
    
            // assign the touchUpInside action for the torch button
            Uiview.toggleTorchButton?.addTarget(self, action: #selector(self.toggleTorchAction(_:)), for: .touchUpInside)
    
            reader.startScanning()
            
            reader.didFindCode = { result in
                print("Completion with result: \(result.value) of type \(result.metadataType)")
            }
        }
    
        // handle the user tapping the torch button    
        @objc func toggleTorchAction(_ button: ToggleTorchButton) {
            reader.toggleTorch()
        }
    
    }
    

    You'll want to do the same thing for the other "built-in" buttons that you're showing.

    By the way, Uiview is a terrible name for an object. Use something like:

    @IBOutlet weak var myScannerView: QRCodeReaderView!
    

    or something similar.