Slide 30
Slide 30 text
struct VisionKitQRCodeScanner: UIViewControllerRepresentable {
@Binding var recognizedPayload: String
func makeUIViewController(context: Context) -> DataScannerViewController {
let dataScannerViewController = DataScannerViewController(
recognizedDataTypes: [.barcode(symbologies: [.qr])]
)
dataScannerViewController.delegate = context.coordinator
try? dataScannerViewController.startScanning()
return dataScannerViewController
}
func updateUIViewController(_ uiViewController: DataScannerViewController, context:
Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
final class Coordinator: NSObject, DataScannerViewControllerDelegate {
private let parent: VisionKitQRCodeScanner
init(parent: VisionKitQRCodeScanner) {
self.parent = parent
}
func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems:
[RecognizedItem], allItems: [RecognizedItem]) {
guard case .barcode(let barcode) = addedItems.first else {
return
}
if let payloadStringValue = barcode.payloadStringValue {
parent.recognizedPayload = payloadStringValue
}
}
func dataScanner(_ dataScanner: DataScannerViewController, didRemove
removedItems: [RecognizedItem], allItems: [RecognizedItem]) {
parent.recognizedPayload = ""
}
}
}
struct AVFoundationQRCodeScanner: UIViewControllerRepresentable {
@Binding var recognizedPayload: String
private let session = AVCaptureSession()
private let sessionQueue = DispatchQueue(label: "sessionQueue")
private let metadataOutput = AVCaptureMetadataOutput()
private let metadataObjectQueue = DispatchQueue(label: "metadataObjectQueue")
private let previewLayer: AVCaptureVideoPreviewLayer
init(recognizedPayload: Binding) {
self._recognizedPayload = recognizedPayload
self.previewLayer = Self.makePreviewLayer(session: self.session)
}
func makeUIViewController(context: Context) -> UIViewController {
let viewController = UIViewController()
viewController.view.layer.masksToBounds = true
viewController.view.layer.addSublayer(previewLayer)
previewLayer.frame = viewController.view.layer.bounds
sessionQueue.async {
self.configureSession(metadataObjectTypes: [.qr], delegate: context.coordinator)
self.session.startRunning()
}
return viewController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
previewLayer.frame = uiViewController.view.layer.bounds
}
func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}
final class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
private let parent: AVFoundationQRCodeScanner
init(parent: AVFoundationQRCodeScanner) {
self.parent = parent
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
guard let metadataObject = metadataObjects.first,
let machineReadableCode = metadataObject as? AVMetadataMachineReadableCodeObject,
machineReadableCode.type == .qr,
let stringValue = machineReadableCode.stringValue
else {
parent.recognizedPayload = ""
return
}
parent.recognizedPayload = stringValue
}
}
}
private extension AVFoundationQRCodeScanner {
func configureSession(
metadataObjectTypes: [AVMetadataObject.ObjectType],
delegate: AVCaptureMetadataOutputObjectsDelegate
) {
defer {
session.commitConfiguration()
}
session.beginConfiguration()
let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
guard let videoDevice else {
return
}
do {
let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice)
if session.canAddInput(videoDeviceInput) {
session.addInput(videoDeviceInput)
}
} catch {
return
}
if session.canAddOutput(metadataOutput) {
session.addOutput(metadataOutput)
metadataOutput.metadataObjectTypes = metadataObjectTypes
metadataOutput.setMetadataObjectsDelegate(delegate, queue: metadataObjectQueue)
}
}
}
private extension AVFoundationQRCodeScanner {
static func makePreviewLayer(session: AVCaptureSession) -> AVCaptureVideoPreviewLayer {
let layer = AVCaptureVideoPreviewLayer(session: session)
layer.videoGravity = .resizeAspectFill
layer.connection?.videoOrientation = .portrait
return layer
}
}
7JTJPO,JU "7'PVOEBUJPO