Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions Sources/CodeScanner/CodeScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,20 @@ public struct ScanResult {

/// The type of code that was matched.
public let type: AVMetadataObject.ObjectType

/// The image of the code that was matched

/// The source of the image where the code was scanned.
public let source: ScanSource

/// The image of the code that was matched.
public let image: UIImage?

/// The corner coordinates of the scanned code.
public let corners: [CGPoint]

/// The bounding rectangle that contains the code that was scanned.
/// When the source is camera the rect is within the local coordinate space of the scanner view.
/// When the source is gallery the rect is in image coordinates.
public let boundingRect: CGRect
}

/// The operating mode for CodeScannerView.
Expand Down Expand Up @@ -70,6 +78,15 @@ public enum ScanMode {
}
}

/// The image source of the ScanResult.
public enum ScanSource {
/// The image was captured by the camera represented by the provided or default `AVCaptureDevice`.
case camera

/// The image was provided by the user's photo gallery using `UIImagePickerController`.
case gallery
}

/// A SwiftUI view that is able to scan barcodes, QR codes, and more, and send back what was found.
/// To use, set `codeTypes` to be an array of things to scan for, e.g. `[.qr]`, and set `completion` to
/// a closure that will be called when scanning has finished. This will be sent the string that was detected or a `ScanError`.
Expand Down
16 changes: 8 additions & 8 deletions Sources/CodeScanner/ScannerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ extension CodeScannerView {
}

#if targetEnvironment(simulator)
var previewLayer: AVCaptureVideoPreviewLayer?

override public func loadView() {
view = UIView()
view.isUserInteractionEnabled = true
Expand Down Expand Up @@ -96,7 +98,7 @@ extension CodeScannerView {
// Send back their simulated data, as if it was one of the types they were scanning for
found(ScanResult(
string: parentView.simulatedData,
type: parentView.codeTypes.first ?? .qr, image: nil, corners: []
type: parentView.codeTypes.first ?? .qr, source: .gallery, image: nil, corners: [], boundingRect: .zero
))
}

Expand Down Expand Up @@ -374,11 +376,8 @@ extension CodeScannerView {
#endif

func updateViewController(isTorchOn: Bool, isGalleryPresented: Bool, isManualCapture: Bool, isManualSelect: Bool) {
guard let videoCaptureDevice = parentView.videoCaptureDevice ?? fallbackVideoCaptureDevice else {
return
}

if videoCaptureDevice.hasTorch {
if let videoCaptureDevice = parentView.videoCaptureDevice ?? fallbackVideoCaptureDevice,
videoCaptureDevice.hasTorch {
try? videoCaptureDevice.lockForConfiguration()
videoCaptureDevice.torchMode = isTorchOn ? .on : .off
videoCaptureDevice.unlockForConfiguration()
Expand Down Expand Up @@ -445,14 +444,15 @@ extension CodeScannerView.ScannerViewController: AVCaptureMetadataOutputObjectsD
!didFinishScanning,
!isCapturing,
let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject,
let boundingRect = previewLayer?.transformedMetadataObject(for: metadataObject)?.bounds,
let stringValue = readableObject.stringValue else {

return
}

handler = { [weak self] image in
guard let self else { return }
let result = ScanResult(string: stringValue, type: readableObject.type, image: image, corners: readableObject.corners)
let result = ScanResult(string: stringValue, type: readableObject.type, source: .camera, image: image, corners: readableObject.corners, boundingRect: boundingRect)

switch parentView.scanMode {
case .once:
Expand Down Expand Up @@ -530,7 +530,7 @@ extension CodeScannerView.ScannerViewController: UIImagePickerControllerDelegate
feature.topLeft
]

let result = ScanResult(string: qrCodeLink, type: .qr, image: qrcodeImg, corners: corners)
let result = ScanResult(string: qrCodeLink, type: .qr, source: .gallery, image: qrcodeImg, corners: corners, boundingRect: feature.bounds)
found(result)
}
}
Expand Down