From 1bf74cc98b0e865176813fc978bb45b1bc202cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Bukowiecki?= Date: Fri, 31 Jan 2025 14:36:58 +0100 Subject: [PATCH 1/2] Add support for zoom of scanner output. (cherry picked from commit 579303ea10b4b578282cc3b48c4896dbe5625abb) --- Sources/CodeScanner/CodeScanner.swift | 4 +++ .../CodeScanner/ScannerViewController.swift | 28 ++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Sources/CodeScanner/CodeScanner.swift b/Sources/CodeScanner/CodeScanner.swift index 85b7994..8530cc8 100644 --- a/Sources/CodeScanner/CodeScanner.swift +++ b/Sources/CodeScanner/CodeScanner.swift @@ -81,6 +81,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { public let scanMode: ScanMode public let manualSelect: Bool public let scanInterval: Double + public let zoomFactor: CGFloat public let showViewfinder: Bool public let requiresPhotoOutput: Bool public var simulatedData = "" @@ -96,6 +97,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { scanMode: ScanMode = .once, manualSelect: Bool = false, scanInterval: Double = 2.0, + zoomFactor: CGFloat = 1, showViewfinder: Bool = false, requiresPhotoOutput: Bool = true, simulatedData: String = "", @@ -112,6 +114,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { self.showViewfinder = showViewfinder self.requiresPhotoOutput = requiresPhotoOutput self.scanInterval = scanInterval + self.zoomFactor = zoomFactor self.simulatedData = simulatedData self.shouldVibrateOnSuccess = shouldVibrateOnSuccess self.isTorchOn = isTorchOn @@ -129,6 +132,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { uiViewController.parentView = self uiViewController.updateViewController( isTorchOn: isTorchOn, + zoomFactor: zoomFactor, isGalleryPresented: isGalleryPresented.wrappedValue, isManualCapture: scanMode.isManual, isManualSelect: manualSelect diff --git a/Sources/CodeScanner/ScannerViewController.swift b/Sources/CodeScanner/ScannerViewController.swift index 292194a..0e3e510 100644 --- a/Sources/CodeScanner/ScannerViewController.swift +++ b/Sources/CodeScanner/ScannerViewController.swift @@ -373,17 +373,11 @@ extension CodeScannerView { } #endif - func updateViewController(isTorchOn: Bool, isGalleryPresented: Bool, isManualCapture: Bool, isManualSelect: Bool) { + func updateViewController(isTorchOn: Bool, zoomFactor: CGFloat, isGalleryPresented: Bool, isManualCapture: Bool, isManualSelect: Bool) { guard let videoCaptureDevice = parentView.videoCaptureDevice ?? fallbackVideoCaptureDevice else { return } - if videoCaptureDevice.hasTorch { - try? videoCaptureDevice.lockForConfiguration() - videoCaptureDevice.torchMode = isTorchOn ? .on : .off - videoCaptureDevice.unlockForConfiguration() - } - if isGalleryPresented, !isGalleryShowing { openGallery() } @@ -392,6 +386,26 @@ extension CodeScannerView { showManualCaptureButton(isManualCapture) showManualSelectButton(isManualSelect) #endif + + let needsZoomUpdate = videoCaptureDevice.videoZoomFactor != zoomFactor + + guard videoCaptureDevice.hasTorch || needsZoomUpdate else { return } + + try? videoCaptureDevice.lockForConfiguration() + + if videoCaptureDevice.hasTorch { + videoCaptureDevice.torchMode = isTorchOn ? .on : .off + } + + if needsZoomUpdate { + let newFactor = max( + videoCaptureDevice.minAvailableVideoZoomFactor, + min(videoCaptureDevice.maxAvailableVideoZoomFactor, zoomFactor) + ) + videoCaptureDevice.videoZoomFactor = newFactor + } + + videoCaptureDevice.unlockForConfiguration() } public func reset() { From 447044ac80275ffdaf18e2bf9ab1cca4fc212277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Bukowiecki?= Date: Thu, 6 Feb 2025 14:40:03 +0100 Subject: [PATCH 2/2] Small change. (cherry picked from commit 30345c6ab6cb4681cdfeeef3691d99f4c3674d69) --- README.md | 1 + Sources/CodeScanner/CodeScanner.swift | 4 ++-- Sources/CodeScanner/ScannerViewController.swift | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6163c15..2ece72d 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ You can provide a variety of extra customization options to `CodeScannerView` in - `scanMode` can be `.once` to scan a single code, `.oncePerCode` to scan many codes but only trigger finding each unique code once, and `.continuous` will keep finding codes until you dismiss the scanner. Default: `.once`. - `scanInterval` controls how fast individual codes should be scanned (in seconds) when running in `.continuous` scan mode. +- `zoomFactor` controls zoom of used capture device. By default it is nil to not interfere with videoCaptureDevice. - `showViewfinder` determines whether to show a box-like viewfinder over the UI. Default: false. - `simulatedData` allows you to provide some test data to use in Simulator, when real scanning isn’t available. Default: an empty string. - `shouldVibrateOnSuccess` allows you to determine whether device should vibrate when a code is found. Default: true. diff --git a/Sources/CodeScanner/CodeScanner.swift b/Sources/CodeScanner/CodeScanner.swift index 8530cc8..57eba69 100644 --- a/Sources/CodeScanner/CodeScanner.swift +++ b/Sources/CodeScanner/CodeScanner.swift @@ -81,7 +81,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { public let scanMode: ScanMode public let manualSelect: Bool public let scanInterval: Double - public let zoomFactor: CGFloat + public let zoomFactor: CGFloat? public let showViewfinder: Bool public let requiresPhotoOutput: Bool public var simulatedData = "" @@ -97,7 +97,7 @@ public struct CodeScannerView: UIViewControllerRepresentable { scanMode: ScanMode = .once, manualSelect: Bool = false, scanInterval: Double = 2.0, - zoomFactor: CGFloat = 1, + zoomFactor: CGFloat? = nil, showViewfinder: Bool = false, requiresPhotoOutput: Bool = true, simulatedData: String = "", diff --git a/Sources/CodeScanner/ScannerViewController.swift b/Sources/CodeScanner/ScannerViewController.swift index 0e3e510..99c62ed 100644 --- a/Sources/CodeScanner/ScannerViewController.swift +++ b/Sources/CodeScanner/ScannerViewController.swift @@ -373,7 +373,7 @@ extension CodeScannerView { } #endif - func updateViewController(isTorchOn: Bool, zoomFactor: CGFloat, isGalleryPresented: Bool, isManualCapture: Bool, isManualSelect: Bool) { + func updateViewController(isTorchOn: Bool, zoomFactor: CGFloat?, isGalleryPresented: Bool, isManualCapture: Bool, isManualSelect: Bool) { guard let videoCaptureDevice = parentView.videoCaptureDevice ?? fallbackVideoCaptureDevice else { return } @@ -387,7 +387,7 @@ extension CodeScannerView { showManualSelectButton(isManualSelect) #endif - let needsZoomUpdate = videoCaptureDevice.videoZoomFactor != zoomFactor + let needsZoomUpdate = zoomFactor != nil && videoCaptureDevice.videoZoomFactor != zoomFactor guard videoCaptureDevice.hasTorch || needsZoomUpdate else { return } @@ -397,7 +397,7 @@ extension CodeScannerView { videoCaptureDevice.torchMode = isTorchOn ? .on : .off } - if needsZoomUpdate { + if needsZoomUpdate, let zoomFactor { let newFactor = max( videoCaptureDevice.minAvailableVideoZoomFactor, min(videoCaptureDevice.maxAvailableVideoZoomFactor, zoomFactor)