data persistence is working!
This commit is contained in:
parent
5eb79457bd
commit
a5eb4a049f
@ -12,6 +12,7 @@
|
|||||||
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 */; };
|
466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */; };
|
||||||
|
466989D92C35206E009884D1 /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 466989D82C35206E009884D1 /* Scan.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
@ -21,6 +22,7 @@
|
|||||||
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>"; };
|
466989D52C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VNDocumentCameraViewControllerR.swift; sourceTree = "<group>"; };
|
||||||
|
466989D82C35206E009884D1 /* Scan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -53,6 +55,7 @@
|
|||||||
466989C52C34DC7A009884D1 /* JustScanIt */ = {
|
466989C52C34DC7A009884D1 /* JustScanIt */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
466989D72C351F23009884D1 /* Model */,
|
||||||
466989D42C34DCB9009884D1 /* Controllers */,
|
466989D42C34DCB9009884D1 /* Controllers */,
|
||||||
466989C62C34DC7A009884D1 /* JustScanItApp.swift */,
|
466989C62C34DC7A009884D1 /* JustScanItApp.swift */,
|
||||||
466989C82C34DC7A009884D1 /* ContentView.swift */,
|
466989C82C34DC7A009884D1 /* ContentView.swift */,
|
||||||
@ -78,6 +81,14 @@
|
|||||||
path = Controllers;
|
path = Controllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
466989D72C351F23009884D1 /* Model */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
466989D82C35206E009884D1 /* Scan.swift */,
|
||||||
|
);
|
||||||
|
path = Model;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -150,6 +161,7 @@
|
|||||||
files = (
|
files = (
|
||||||
466989C92C34DC7A009884D1 /* ContentView.swift in Sources */,
|
466989C92C34DC7A009884D1 /* ContentView.swift in Sources */,
|
||||||
466989C72C34DC7A009884D1 /* JustScanItApp.swift in Sources */,
|
466989C72C34DC7A009884D1 /* JustScanItApp.swift in Sources */,
|
||||||
|
466989D92C35206E009884D1 /* Scan.swift in Sources */,
|
||||||
466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */,
|
466989D62C34DCE4009884D1 /* VNDocumentCameraViewControllerR.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -6,12 +6,17 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import SwiftData
|
||||||
import AVKit
|
import AVKit
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
|
@Environment(\.modelContext) var ctx
|
||||||
|
|
||||||
@State private var scannedImages: [UIImage] = []
|
@State private var scannedImages: [UIImage] = []
|
||||||
@State private var isShowingVNDocumentCameraView = false
|
@State private var isShowingVNDocumentCameraView = false
|
||||||
|
|
||||||
|
@Query var scans: [Scan]
|
||||||
|
|
||||||
var isAuthorized: Bool {
|
var isAuthorized: Bool {
|
||||||
get async {
|
get async {
|
||||||
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
@ -23,6 +28,8 @@ struct ContentView: View {
|
|||||||
// explicitly prompt them for approval.
|
// explicitly prompt them for approval.
|
||||||
if status == .notDetermined {
|
if status == .notDetermined {
|
||||||
isAuthorized = await AVCaptureDevice.requestAccess(for: .video)
|
isAuthorized = await AVCaptureDevice.requestAccess(for: .video)
|
||||||
|
} else if status == .denied {
|
||||||
|
// TODO: show alert when denied
|
||||||
}
|
}
|
||||||
|
|
||||||
return isAuthorized
|
return isAuthorized
|
||||||
@ -31,19 +38,22 @@ struct ContentView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
Grid {
|
ScrollView {
|
||||||
ForEach(scannedImages, id: \.self) { image in
|
ForEach(scans, id: \.self) { scan in
|
||||||
VStack {
|
HStack {
|
||||||
Image(uiImage: image)
|
ForEach(scan.uiImages, id: \.self) { image in
|
||||||
.resizable()
|
Image(uiImage: image)
|
||||||
.scaledToFit()
|
.resizable()
|
||||||
.frame(width: 100, height: 100)
|
.scaledToFit()
|
||||||
.padding()
|
.frame(width: 100, height: 100)
|
||||||
|
.padding()
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Just Scan It!")
|
.navigationTitle("Just Scan It!")
|
||||||
.sheet(isPresented: $isShowingVNDocumentCameraView) {
|
.sheet(isPresented: $isShowingVNDocumentCameraView, onDismiss: saveImages) {
|
||||||
VNDocumentCameraViewControllerRepresentable(scanResult: $scannedImages)
|
VNDocumentCameraViewControllerRepresentable(scanResult: $scannedImages)
|
||||||
}
|
}
|
||||||
.toolbar {
|
.toolbar {
|
||||||
@ -57,12 +67,19 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func showVNDocumentCameraView() {
|
private func showVNDocumentCameraView() {
|
||||||
Task {
|
Task { guard await isAuthorized else { return } }
|
||||||
guard await isAuthorized else { return }
|
|
||||||
}
|
|
||||||
|
|
||||||
isShowingVNDocumentCameraView = true
|
isShowingVNDocumentCameraView = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func saveImages() {
|
||||||
|
let newScan = Scan(images: scannedImages)
|
||||||
|
|
||||||
|
ctx.insert(newScan)
|
||||||
|
try? ctx.save()
|
||||||
|
|
||||||
|
scannedImages = []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
|
@ -6,12 +6,26 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import SwiftData
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct JustScanItApp: App {
|
struct JustScanItApp: App {
|
||||||
|
var sharedModelContainer: ModelContainer = {
|
||||||
|
let schema = Schema([ Scan.self ])
|
||||||
|
|
||||||
|
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
|
||||||
|
|
||||||
|
do {
|
||||||
|
return try ModelContainer(for: schema, configurations: [modelConfiguration])
|
||||||
|
} catch {
|
||||||
|
fatalError("Could not create ModelContainer: \(error)")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView()
|
||||||
}
|
}
|
||||||
|
.modelContainer(sharedModelContainer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
JustScanIt/Model/Scan.swift
Normal file
37
JustScanIt/Model/Scan.swift
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Scan.swift
|
||||||
|
// JustScanIt
|
||||||
|
//
|
||||||
|
// Created by Pradyun Setti on 03/07/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftData
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@Model
|
||||||
|
final class Scan {
|
||||||
|
let timestamp: Date
|
||||||
|
var images: [Data]
|
||||||
|
|
||||||
|
var uiImages: [UIImage] {
|
||||||
|
self.images.map { UIImage(data: $0) ?? UIImage(systemName: "exclamationmark.questionmark")! }
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.timestamp = Date()
|
||||||
|
self.images = []
|
||||||
|
}
|
||||||
|
|
||||||
|
init(images: [Data]) {
|
||||||
|
self.timestamp = Date()
|
||||||
|
self.images = images
|
||||||
|
}
|
||||||
|
|
||||||
|
init(images: [UIImage]) {
|
||||||
|
self.timestamp = Date()
|
||||||
|
|
||||||
|
self.images = images.map{ $0.pngData() ?? Data() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user