From d1d7e2b8db7222cb1714626048f31aaf8eceb1f0 Mon Sep 17 00:00:00 2001 From: Peter Salz Date: Tue, 27 Feb 2024 12:09:50 +0100 Subject: [PATCH 1/4] Renamed "requirePhotoOutput" to "requiresPhotoOutput" --- Sources/CodeScanner/CodeScanner.swift | 14 +++++++++++--- Sources/CodeScanner/ScannerViewController.swift | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Sources/CodeScanner/CodeScanner.swift b/Sources/CodeScanner/CodeScanner.swift index de40c30..42e3eff 100644 --- a/Sources/CodeScanner/CodeScanner.swift +++ b/Sources/CodeScanner/CodeScanner.swift @@ -81,7 +81,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { public let manualSelect: Bool public let scanInterval: Double public let showViewfinder: Bool - public let requirePhotoOutput: Bool + public let requiresPhotoOutput: Bool public var simulatedData = "" public var shouldVibrateOnSuccess: Bool public var isTorchOn: Bool @@ -96,7 +96,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { manualSelect: Bool = false, scanInterval: Double = 2.0, showViewfinder: Bool = false, - requirePhotoOutput: Bool = true, + requiresPhotoOutput: Bool = true, simulatedData: String = "", shouldVibrateOnSuccess: Bool = true, isTorchOn: Bool = false, @@ -109,7 +109,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { self.scanMode = scanMode self.manualSelect = manualSelect self.showViewfinder = showViewfinder - self.requirePhotoOutput = requirePhotoOutput + self.requiresPhotoOutput = requiresPhotoOutput self.scanInterval = scanInterval self.simulatedData = simulatedData self.shouldVibrateOnSuccess = shouldVibrateOnSuccess @@ -136,6 +136,14 @@ public struct CodeScannerView: UIViewControllerRepresentable { } +extension CodeScannerView { + + @available(*, deprecated, renamed: "requiresPhotoOutput") + public var requirePhotoOutput: Bool { + requiresPhotoOutput + } +} + @available(macCatalyst 14.0, *) struct CodeScannerView_Previews: PreviewProvider { static var previews: some View { diff --git a/Sources/CodeScanner/ScannerViewController.swift b/Sources/CodeScanner/ScannerViewController.swift index 366419d..6e1b5e0 100644 --- a/Sources/CodeScanner/ScannerViewController.swift +++ b/Sources/CodeScanner/ScannerViewController.swift @@ -476,7 +476,7 @@ extension CodeScannerView.ScannerViewController: AVCaptureMetadataOutputObjectsD } } - if parentView.requirePhotoOutput { + if parentView.requiresPhotoOutput { isCapturing = true photoOutput.capturePhoto(with: AVCapturePhotoSettings(), delegate: self) } else { From 205588f27c51ea60197ee2772132123db113aac0 Mon Sep 17 00:00:00 2001 From: Peter Salz Date: Tue, 27 Feb 2024 12:24:30 +0100 Subject: [PATCH 2/4] Improved code readability of ScannerViewController. --- Sources/CodeScanner/CodeScanner.swift | 1 + .../CodeScanner/ScannerViewController.swift | 153 +++++++++--------- 2 files changed, 80 insertions(+), 74 deletions(-) diff --git a/Sources/CodeScanner/CodeScanner.swift b/Sources/CodeScanner/CodeScanner.swift index 42e3eff..cffaf83 100644 --- a/Sources/CodeScanner/CodeScanner.swift +++ b/Sources/CodeScanner/CodeScanner.swift @@ -136,6 +136,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { } +@available(macCatalyst 14.0, *) extension CodeScannerView { @available(*, deprecated, renamed: "requiresPhotoOutput") diff --git a/Sources/CodeScanner/ScannerViewController.swift b/Sources/CodeScanner/ScannerViewController.swift index 6e1b5e0..171b668 100644 --- a/Sources/CodeScanner/ScannerViewController.swift +++ b/Sources/CodeScanner/ScannerViewController.swift @@ -185,11 +185,11 @@ extension CodeScannerView { previewLayer.frame = view.layer.bounds previewLayer.videoGravity = .resizeAspectFill view.layer.addSublayer(previewLayer) - addviewfinder() + addViewFinder() reset() - if (captureSession.isRunning == false) { + if !captureSession.isRunning { DispatchQueue.global(qos: .userInteractive).async { self.captureSession?.startRunning() } @@ -232,7 +232,7 @@ extension CodeScannerView { NotificationCenter.default.addObserver( self, selector: #selector(updateOrientation), - name: Notification.Name("UIDeviceOrientationDidChangeNotification"), + name: UIDevice.orientationDidChangeNotification, object: nil ) } @@ -257,7 +257,7 @@ extension CodeScannerView { return } - if (captureSession!.canAddInput(videoInput)) { + if captureSession!.canAddInput(videoInput) { captureSession!.addInput(videoInput) } else { didFail(reason: .badInput) @@ -265,9 +265,9 @@ extension CodeScannerView { } let metadataOutput = AVCaptureMetadataOutput() - if (captureSession!.canAddOutput(metadataOutput)) { + if captureSession!.canAddOutput(metadataOutput) { captureSession!.addOutput(metadataOutput) - captureSession?.addOutput(photoOutput) + captureSession!.addOutput(photoOutput) metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) metadataOutput.metadataObjectTypes = parentView.codeTypes } else { @@ -276,7 +276,7 @@ extension CodeScannerView { } } - private func addviewfinder() { + private func addViewFinder() { guard showViewfinder, let imageView = viewFinder else { return } view.addSubview(imageView) @@ -292,7 +292,7 @@ extension CodeScannerView { override public func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - if (captureSession?.isRunning == true) { + if captureSession?.isRunning == true { DispatchQueue.global(qos: .userInteractive).async { self.captureSession?.stopRunning() } @@ -329,7 +329,7 @@ extension CodeScannerView { return } - // Focus to the correct point, make continiuous focus and exposure so the point stays sharp when moving the device closer + // Focus to the correct point, make continuous focus and exposure so the point stays sharp when moving the device closer device.focusPointOfInterest = focusPoint device.focusMode = .continuousAutoFocus device.exposurePointOfInterest = focusPoint @@ -383,7 +383,7 @@ extension CodeScannerView { videoCaptureDevice.unlockForConfiguration() } - if isGalleryPresented && !isGalleryShowing { + if isGalleryPresented, !isGalleryShowing { openGallery() } @@ -405,11 +405,11 @@ extension CodeScannerView { lastTime = Date() } - func isPastScanInterval() -> Bool { + var isPastScanInterval: Bool { Date().timeIntervalSince(lastTime) >= parentView.scanInterval } - func isWithinManualCaptureInterval() -> Bool { + var isWithinManualCaptureInterval: Bool { Date().timeIntervalSince(lastTime) <= 0.5 } @@ -435,53 +435,56 @@ extension CodeScannerView { @available(macCatalyst 14.0, *) extension CodeScannerView.ScannerViewController: AVCaptureMetadataOutputObjectsDelegate { public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { - if let metadataObject = metadataObjects.first { - guard !parentView.isPaused && !didFinishScanning && !isCapturing, - let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject, - let stringValue = readableObject.stringValue - else { - return - } - handler = { [self] image in - let result = ScanResult(string: stringValue, type: readableObject.type, image: image, corners: readableObject.corners) - switch parentView.scanMode { - case .once: + guard let metadataObject = metadataObjects.first, + !parentView.isPaused, + !didFinishScanning, + !isCapturing, + let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject, + let stringValue = readableObject.stringValue else { + + return + } + + handler = { [self] image in + let result = ScanResult(string: stringValue, type: readableObject.type, image: image, corners: readableObject.corners) + + switch parentView.scanMode { + case .once: + found(result) + // make sure we only trigger scan once per use + didFinishScanning = true + + case .manual: + if !didFinishScanning, isWithinManualCaptureInterval { found(result) - // make sure we only trigger scan once per use didFinishScanning = true + } - case .manual: - if !didFinishScanning, isWithinManualCaptureInterval() { - found(result) - didFinishScanning = true - } - - case .oncePerCode: - if !codesFound.contains(stringValue) { - codesFound.insert(stringValue) - found(result) - } + case .oncePerCode: + if !codesFound.contains(stringValue) { + codesFound.insert(stringValue) + found(result) + } - case .continuous: - if isPastScanInterval() { - found(result) - } + case .continuous: + if isPastScanInterval { + found(result) + } - case .continuousExcept(let ignoredList): - if isPastScanInterval() && !ignoredList.contains(stringValue) { - found(result) - } + case .continuousExcept(let ignoredList): + if isPastScanInterval, !ignoredList.contains(stringValue) { + found(result) } } + } - if parentView.requiresPhotoOutput { - isCapturing = true - photoOutput.capturePhoto(with: AVCapturePhotoSettings(), delegate: self) - } else { - handler?(nil) - } + if parentView.requiresPhotoOutput { + isCapturing = true + photoOutput.capturePhoto(with: AVCapturePhotoSettings(), delegate: self) + } else { + handler?(nil) } } } @@ -493,40 +496,42 @@ extension CodeScannerView.ScannerViewController: UIImagePickerControllerDelegate public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) { isGalleryShowing = false - if let qrcodeImg = info[.originalImage] as? UIImage { - let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])! - let ciImage = CIImage(image:qrcodeImg)! - var qrCodeLink = "" - - let features = detector.features(in: ciImage) - - for feature in features as! [CIQRCodeFeature] { - qrCodeLink = feature.messageString! - if qrCodeLink == "" { - didFail(reason: .badOutput) - } else { - let corners = [ - feature.bottomLeft, - feature.bottomRight, - feature.topRight, - feature.topLeft - ] - let result = ScanResult(string: qrCodeLink, type: .qr, image: qrcodeImg, corners: corners) - found(result) - } + defer { + dismiss(animated: true) + } - } + guard let qrcodeImg = info[.originalImage] as? UIImage, + let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]), + let ciImage = CIImage(image:qrcodeImg) else { - } else { print("Something went wrong") + return } - dismiss(animated: true, completion: nil) + var qrCodeLink = "" + + let features = detector.features(in: ciImage) + + for feature in features as! [CIQRCodeFeature] { + qrCodeLink = feature.messageString! + if qrCodeLink.isEmpty { + didFail(reason: .badOutput) + } else { + let corners = [ + feature.bottomLeft, + feature.bottomRight, + feature.topRight, + feature.topLeft + ] + let result = ScanResult(string: qrCodeLink, type: .qr, image: qrcodeImg, corners: corners) + found(result) + } + } } public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { isGalleryShowing = false - dismiss(animated: true, completion: nil) + dismiss(animated: true) } } From 739790ae2739aba771268ade31f7c89d64e42fb2 Mon Sep 17 00:00:00 2001 From: Peter Salz Date: Tue, 27 Feb 2024 12:25:04 +0100 Subject: [PATCH 3/4] Removed the macOS target since it doesn't compile anyway due to the unchecked use of UIKit. --- Package.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index c1eba9e..377f4ef 100644 --- a/Package.swift +++ b/Package.swift @@ -6,8 +6,7 @@ import PackageDescription let package = Package( name: "CodeScanner", platforms: [ - .iOS(.v13), - .macOS(.v11) + .iOS(.v13) ], products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. From 83db36b3f5403db09fd33df287cc78f5f33f8c8f Mon Sep 17 00:00:00 2001 From: Peter Salz Date: Fri, 1 Mar 2024 10:46:38 +0100 Subject: [PATCH 4/4] Cleanup of a print statement --- Sources/CodeScanner/ScannerViewController.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/CodeScanner/ScannerViewController.swift b/Sources/CodeScanner/ScannerViewController.swift index 171b668..f12e993 100644 --- a/Sources/CodeScanner/ScannerViewController.swift +++ b/Sources/CodeScanner/ScannerViewController.swift @@ -504,7 +504,6 @@ extension CodeScannerView.ScannerViewController: UIImagePickerControllerDelegate let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]), let ciImage = CIImage(image:qrcodeImg) else { - print("Something went wrong") return }