Skip to content

Commit 88a6132

Browse files
author
Nathan Fallet
authored
Merge pull request #95 from zappycode/main
2 parents 9aef09b + 727b6a5 commit 88a6132

File tree

2 files changed

+55
-26
lines changed

2 files changed

+55
-26
lines changed

Sources/CodeScanner/CodeScanner.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ public struct ScanResult {
3434

3535
/// The type of code that was matched.
3636
public let type: AVMetadataObject.ObjectType
37+
38+
/// The image of the code that was matched
39+
public let image: UIImage?
3740
}
3841

3942
/// The operating mode for CodeScannerView.

Sources/CodeScanner/ScannerViewController.swift

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import UIKit
1313
extension CodeScannerView {
1414

1515
public class ScannerViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, AVCaptureMetadataOutputObjectsDelegate {
16-
16+
private let photoOutput = AVCapturePhotoOutput()
17+
private var isCapturing = false
18+
private var handler: ((UIImage) -> Void)?
1719
var parentView: CodeScannerView!
1820
var codesFound = Set<String>()
1921
var didFinishScanning = false
@@ -68,7 +70,7 @@ extension CodeScannerView {
6870
if qrCodeLink == "" {
6971
didFail(reason: .badOutput)
7072
} else {
71-
let result = ScanResult(string: qrCodeLink, type: .qr)
73+
let result = ScanResult(string: qrCodeLink, type: .qr, image: qrcodeImg)
7274
found(result)
7375
}
7476
} else {
@@ -122,7 +124,7 @@ extension CodeScannerView {
122124
// Send back their simulated data, as if it was one of the types they were scanning for
123125
found(ScanResult(
124126
string: parentView.simulatedData,
125-
type: parentView.codeTypes.first ?? .qr
127+
type: parentView.codeTypes.first ?? .qr, image: nil
126128
))
127129
}
128130

@@ -280,12 +282,11 @@ extension CodeScannerView {
280282
didFail(reason: .badInput)
281283
return
282284
}
283-
284285
let metadataOutput = AVCaptureMetadataOutput()
285286

286287
if (captureSession!.canAddOutput(metadataOutput)) {
287288
captureSession!.addOutput(metadataOutput)
288-
289+
captureSession?.addOutput(photoOutput)
289290
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
290291
metadataOutput.metadataObjectTypes = parentView.codeTypes
291292
} else {
@@ -425,32 +426,41 @@ extension CodeScannerView {
425426
if let metadataObject = metadataObjects.first {
426427
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
427428
guard let stringValue = readableObject.stringValue else { return }
429+
428430
guard didFinishScanning == false else { return }
429-
let result = ScanResult(string: stringValue, type: readableObject.type)
430-
431-
switch parentView.scanMode {
432-
case .once:
433-
found(result)
434-
// make sure we only trigger scan once per use
435-
didFinishScanning = true
436-
437-
case .manual:
438-
if !didFinishScanning, isWithinManualCaptureInterval() {
439-
found(result)
440-
didFinishScanning = true
441-
}
431+
432+
let photoSettings = AVCapturePhotoSettings()
433+
guard !isCapturing else { return }
434+
isCapturing = true
435+
436+
handler = { [self] image in
437+
let result = ScanResult(string: stringValue, type: readableObject.type, image: image)
442438

443-
case .oncePerCode:
444-
if !codesFound.contains(stringValue) {
445-
codesFound.insert(stringValue)
446-
found(result)
447-
}
448-
449-
case .continuous:
450-
if isPastScanInterval() {
439+
switch parentView.scanMode {
440+
case .once:
451441
found(result)
442+
// make sure we only trigger scan once per use
443+
didFinishScanning = true
444+
445+
case .manual:
446+
if !didFinishScanning, isWithinManualCaptureInterval() {
447+
found(result)
448+
didFinishScanning = true
449+
}
450+
451+
case .oncePerCode:
452+
if !codesFound.contains(stringValue) {
453+
codesFound.insert(stringValue)
454+
found(result)
455+
}
456+
457+
case .continuous:
458+
if isPastScanInterval() {
459+
found(result)
460+
}
452461
}
453462
}
463+
photoOutput.capturePhoto(with: photoSettings, delegate: self)
454464
}
455465
}
456466

@@ -478,3 +488,19 @@ extension CodeScannerView {
478488

479489
}
480490
}
491+
492+
@available(macCatalyst 14.0, *)
493+
extension CodeScannerView.ScannerViewController: AVCapturePhotoCaptureDelegate {
494+
public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
495+
isCapturing = false
496+
guard let imageData = photo.fileDataRepresentation() else {
497+
print("Error while generating image from photo capture data.");
498+
return
499+
}
500+
guard let qrImage = UIImage(data: imageData) else {
501+
print("Unable to generate UIImage from image data.");
502+
return
503+
}
504+
handler?(qrImage)
505+
}
506+
}

0 commit comments

Comments
 (0)