Added the document camera controller and very basic mockup of the view

This commit is contained in:
breadone 2024-07-03 17:51:16 +12:00
parent 66c7a37e32
commit 5eb79457bd
No known key found for this signature in database
4 changed files with 137 additions and 13 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Build/

View File

@ -11,6 +11,7 @@
466989C92C34DC7A009884D1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989C82C34DC7A009884D1 /* ContentView.swift */; }; 466989C92C34DC7A009884D1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989C82C34DC7A009884D1 /* ContentView.swift */; };
466989CB2C34DC7B009884D1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 466989CA2C34DC7B009884D1 /* Assets.xcassets */; }; 466989CB2C34DC7B009884D1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 466989CA2C34DC7B009884D1 /* Assets.xcassets */; };
466989CE2C34DC7B009884D1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 466989CD2C34DC7B009884D1 /* Preview Assets.xcassets */; }; 466989CE2C34DC7B009884D1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 466989CD2C34DC7B009884D1 /* Preview Assets.xcassets */; };
466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -19,6 +20,7 @@
466989C82C34DC7A009884D1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; 466989C82C34DC7A009884D1 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
466989CA2C34DC7B009884D1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 466989CA2C34DC7B009884D1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
466989CD2C34DC7B009884D1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; }; 466989CD2C34DC7B009884D1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VNDocumentCameraViewControllerR.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -51,6 +53,7 @@
466989C52C34DC7A009884D1 /* JustScanIt */ = { 466989C52C34DC7A009884D1 /* JustScanIt */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
466989D42C34DCB9009884D1 /* Controllers */,
466989C62C34DC7A009884D1 /* JustScanItApp.swift */, 466989C62C34DC7A009884D1 /* JustScanItApp.swift */,
466989C82C34DC7A009884D1 /* ContentView.swift */, 466989C82C34DC7A009884D1 /* ContentView.swift */,
466989CA2C34DC7B009884D1 /* Assets.xcassets */, 466989CA2C34DC7B009884D1 /* Assets.xcassets */,
@ -67,6 +70,14 @@
path = "Preview Content"; path = "Preview Content";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
466989D42C34DCB9009884D1 /* Controllers */ = {
isa = PBXGroup;
children = (
466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */,
);
path = Controllers;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -139,6 +150,7 @@
files = ( files = (
466989C92C34DC7A009884D1 /* ContentView.swift in Sources */, 466989C92C34DC7A009884D1 /* ContentView.swift in Sources */,
466989C72C34DC7A009884D1 /* JustScanItApp.swift in Sources */, 466989C72C34DC7A009884D1 /* JustScanItApp.swift in Sources */,
466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -275,11 +287,14 @@
DEVELOPMENT_TEAM = 9MP5435PRF; DEVELOPMENT_TEAM = 9MP5435PRF;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Just Scan It";
INFOPLIST_KEY_NSCameraUsageDescription = "Scan documents with the camera.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -287,9 +302,13 @@
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.breadone.JustScanIt; PRODUCT_BUNDLE_IDENTIFIER = xyz.breadone.JustScanIt;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = 1;
}; };
name = Debug; name = Debug;
}; };
@ -304,11 +323,14 @@
DEVELOPMENT_TEAM = 9MP5435PRF; DEVELOPMENT_TEAM = 9MP5435PRF;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Just Scan It";
INFOPLIST_KEY_NSCameraUsageDescription = "Scan documents with the camera.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -316,9 +338,13 @@
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = xyz.breadone.JustScanIt; PRODUCT_BUNDLE_IDENTIFIER = xyz.breadone.JustScanIt;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = 1;
}; };
name = Release; name = Release;
}; };

View File

@ -6,17 +6,63 @@
// //
import SwiftUI import SwiftUI
import AVKit
struct ContentView: View { struct ContentView: View {
var body: some View { @State private var scannedImages: [UIImage] = []
VStack { @State private var isShowingVNDocumentCameraView = false
Image(systemName: "globe")
.imageScale(.large) var isAuthorized: Bool {
.foregroundStyle(.tint) get async {
Text("Hello, world!") let status = AVCaptureDevice.authorizationStatus(for: .video)
// Determine if the user previously authorized camera access.
var isAuthorized = status == .authorized
// If the system hasn't determined the user's authorization status,
// explicitly prompt them for approval.
if status == .notDetermined {
isAuthorized = await AVCaptureDevice.requestAccess(for: .video)
} }
return isAuthorized
}
}
var body: some View {
NavigationView {
Grid {
ForEach(scannedImages, id: \.self) { image in
VStack {
Image(uiImage: image)
.resizable()
.scaledToFit()
.frame(width: 100, height: 100)
.padding() .padding()
} }
}
}
.navigationTitle("Just Scan It!")
.sheet(isPresented: $isShowingVNDocumentCameraView) {
VNDocumentCameraViewControllerRepresentable(scanResult: $scannedImages)
}
.toolbar {
ToolbarItem {
Button(action: showVNDocumentCameraView) {
Image(systemName: "scanner")
}
}
}
}
}
private func showVNDocumentCameraView() {
Task {
guard await isAuthorized else { return }
}
isShowingVNDocumentCameraView = true
}
} }
#Preview { #Preview {

View File

@ -0,0 +1,51 @@
//
// VNDocumentCameraViewControllerR.swift
// JustScanIt
//
// Created by Pradyun Setti on 03/07/2024.
//
import SwiftUI
import VisionKit
struct VNDocumentCameraViewControllerRepresentable: UIViewControllerRepresentable {
@Binding var scanResult: [UIImage]
func makeUIViewController(context: Context) -> VNDocumentCameraViewController {
let documentCameraViewController = VNDocumentCameraViewController()
documentCameraViewController.delegate = context.coordinator
return documentCameraViewController
}
func updateUIViewController(_ uiViewController: VNDocumentCameraViewController, context: Context) { }
func makeCoordinator() -> Coordinator {
Coordinator(scanResult: $scanResult)
}
final class Coordinator: NSObject, VNDocumentCameraViewControllerDelegate {
@Binding var scanResult: [UIImage]
init(scanResult: Binding<[UIImage]>) {
_scanResult = scanResult
}
/// Tells the delegate that the user successfully saved a scanned document from the document camera.
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
controller.dismiss(animated: true, completion: nil)
scanResult = (0..<scan.pageCount).compactMap { scan.imageOfPage(at: $0) }
}
// Tells the delegate that the user canceled out of the document scanner camera.
func documentCameraViewControllerDidCancel(_ controller: VNDocumentCameraViewController) {
controller.dismiss(animated: true, completion: nil)
}
/// Tells the delegate that document scanning failed while the camera view controller was active.
func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFailWithError error: Error) {
print("Document scanner error: \(error.localizedDescription)")
controller.dismiss(animated: true, completion: nil)
}
}
}