Skip to content

Commit

Permalink
Merge pull request #95 from zappycode/main
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathan Fallet authored Feb 8, 2023
2 parents 9aef09b + 727b6a5 commit 88a6132
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 26 deletions.
3 changes: 3 additions & 0 deletions Sources/CodeScanner/CodeScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public struct ScanResult {

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

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

/// The operating mode for CodeScannerView.
Expand Down
78 changes: 52 additions & 26 deletions Sources/CodeScanner/ScannerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import UIKit
extension CodeScannerView {

public class ScannerViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, AVCaptureMetadataOutputObjectsDelegate {

private let photoOutput = AVCapturePhotoOutput()
private var isCapturing = false
private var handler: ((UIImage) -> Void)?
var parentView: CodeScannerView!
var codesFound = Set<String>()
var didFinishScanning = false
Expand Down Expand Up @@ -68,7 +70,7 @@ extension CodeScannerView {
if qrCodeLink == "" {
didFail(reason: .badOutput)
} else {
let result = ScanResult(string: qrCodeLink, type: .qr)
let result = ScanResult(string: qrCodeLink, type: .qr, image: qrcodeImg)
found(result)
}
} else {
Expand Down Expand Up @@ -122,7 +124,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
type: parentView.codeTypes.first ?? .qr, image: nil
))
}

Expand Down Expand Up @@ -280,12 +282,11 @@ extension CodeScannerView {
didFail(reason: .badInput)
return
}

let metadataOutput = AVCaptureMetadataOutput()

if (captureSession!.canAddOutput(metadataOutput)) {
captureSession!.addOutput(metadataOutput)

captureSession?.addOutput(photoOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = parentView.codeTypes
} else {
Expand Down Expand Up @@ -425,32 +426,41 @@ extension CodeScannerView {
if let metadataObject = metadataObjects.first {
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
guard let stringValue = readableObject.stringValue else { return }

guard didFinishScanning == false else { return }
let result = ScanResult(string: stringValue, type: readableObject.type)

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)
didFinishScanning = true
}

let photoSettings = AVCapturePhotoSettings()
guard !isCapturing else { return }
isCapturing = true

handler = { [self] image in
let result = ScanResult(string: stringValue, type: readableObject.type, image: image)

case .oncePerCode:
if !codesFound.contains(stringValue) {
codesFound.insert(stringValue)
found(result)
}

case .continuous:
if isPastScanInterval() {
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)
didFinishScanning = true
}

case .oncePerCode:
if !codesFound.contains(stringValue) {
codesFound.insert(stringValue)
found(result)
}

case .continuous:
if isPastScanInterval() {
found(result)
}
}
}
photoOutput.capturePhoto(with: photoSettings, delegate: self)
}
}

Expand Down Expand Up @@ -478,3 +488,19 @@ extension CodeScannerView {

}
}

@available(macCatalyst 14.0, *)
extension CodeScannerView.ScannerViewController: AVCapturePhotoCaptureDelegate {
public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
isCapturing = false
guard let imageData = photo.fileDataRepresentation() else {
print("Error while generating image from photo capture data.");
return
}
guard let qrImage = UIImage(data: imageData) else {
print("Unable to generate UIImage from image data.");
return
}
handler?(qrImage)
}
}

0 comments on commit 88a6132

Please sign in to comment.