Renamming FrameHandler in CameraModel. Renamming FrameView in CameraView. Refactoring ViewModel: Retrieving output in progress, removing permissionGranted property: I use it directly, adding permissionAlert property for UI.
This commit is contained in:
parent
0190c52bd5
commit
79748524c6
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// FrameHandler.swift
|
// CameraModel.swift
|
||||||
// macamera
|
// macamera
|
||||||
//
|
//
|
||||||
// Created by Maxime on 06/05/2025.
|
// Created by Maxime on 06/05/2025.
|
||||||
@ -10,11 +10,13 @@
|
|||||||
import AVFoundation
|
import AVFoundation
|
||||||
import CoreImage
|
import CoreImage
|
||||||
|
|
||||||
class FrameHandler: NSObject, ObservableObject {
|
class CameraModel: NSObject, ObservableObject {
|
||||||
|
|
||||||
@Published var frame: CGImage?
|
@Published var frame: CGImage?
|
||||||
|
|
||||||
private var permissionGranted: Bool = true
|
@Published var permissionAlert = false
|
||||||
|
@Published var output = AVCapturePhotoOutput()
|
||||||
|
|
||||||
private let captureSession = AVCaptureSession()
|
private let captureSession = AVCaptureSession()
|
||||||
private let context = CIContext()
|
private let context = CIContext()
|
||||||
|
|
||||||
@ -22,37 +24,43 @@ class FrameHandler: NSObject, ObservableObject {
|
|||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
Task.detached(priority: .background) {
|
Task.detached(priority: .background) {
|
||||||
self.permissionGranted = await self.checkPermission()
|
let accessIsGranted = await self.checkPermission()
|
||||||
self.setupCaptureSession()
|
self.setupCaptureSession(accessIsGranted: accessIsGranted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Convenience Methods
|
// MARK: - Convenience Methods
|
||||||
|
|
||||||
extension FrameHandler {
|
extension CameraModel {
|
||||||
|
|
||||||
private func checkPermission() async -> Bool {
|
private func checkPermission() async -> Bool {
|
||||||
switch AVCaptureDevice.authorizationStatus(for: .video) {
|
switch AVCaptureDevice.authorizationStatus(for: .video) {
|
||||||
case .notDetermined:
|
|
||||||
return await AVCaptureDevice.requestAccess(for: .video)
|
|
||||||
case .authorized:
|
case .authorized:
|
||||||
return true
|
return true
|
||||||
|
case .notDetermined:
|
||||||
|
let isGranted = await AVCaptureDevice.requestAccess(for: .video)
|
||||||
|
|
||||||
|
if isGranted == false {
|
||||||
|
permissionAlert.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
return isGranted
|
||||||
default:
|
default:
|
||||||
|
permissionAlert.toggle()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupCaptureSession() {
|
private func setupCaptureSession(accessIsGranted: Bool) {
|
||||||
let videoOutput = AVCaptureVideoDataOutput()
|
guard accessIsGranted else { return }
|
||||||
|
|
||||||
guard permissionGranted else { return }
|
|
||||||
guard let videoDevice = AVCaptureDevice.default(.builtInDualWideCamera, for: .video, position: .back) else { return }
|
guard let videoDevice = AVCaptureDevice.default(.builtInDualWideCamera, for: .video, position: .back) else { return }
|
||||||
guard let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice) else { return }
|
guard let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice) else { return }
|
||||||
|
|
||||||
guard captureSession.canAddInput(videoDeviceInput) else { return }
|
guard captureSession.canAddInput(videoDeviceInput) else { return }
|
||||||
captureSession.addInput(videoDeviceInput)
|
captureSession.addInput(videoDeviceInput)
|
||||||
|
|
||||||
|
let videoOutput = AVCaptureVideoDataOutput()
|
||||||
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sampleBufferQueue"))
|
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "sampleBufferQueue"))
|
||||||
captureSession.addOutput(videoOutput)
|
captureSession.addOutput(videoOutput)
|
||||||
|
|
||||||
@ -64,7 +72,7 @@ extension FrameHandler {
|
|||||||
|
|
||||||
// MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
|
// MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
|
||||||
|
|
||||||
extension FrameHandler: AVCaptureVideoDataOutputSampleBufferDelegate {
|
extension CameraModel: AVCaptureVideoDataOutputSampleBufferDelegate {
|
||||||
|
|
||||||
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
|
||||||
guard let cgImage = imageFromSampleBuffer(sampleBuffer: sampleBuffer) else { return }
|
guard let cgImage = imageFromSampleBuffer(sampleBuffer: sampleBuffer) else { return }
|
@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// FrameView.swift
|
// CameraView.swift
|
||||||
// macamera
|
// macamera
|
||||||
//
|
//
|
||||||
// Created by Maxime on 06/05/2025.
|
// Created by Maxime on 06/05/2025.
|
||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct FrameView: View {
|
struct CameraView: View {
|
||||||
|
|
||||||
var image: CGImage?
|
var image: CGImage?
|
||||||
private let label = Text("frame")
|
private let label = Text("frame")
|
||||||
@ -22,5 +22,5 @@ struct FrameView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
FrameView()
|
CameraView()
|
||||||
}
|
}
|
@ -8,10 +8,10 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@StateObject private var model = FrameHandler()
|
@StateObject private var model = CameraModel()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
FrameView(image: model.frame)
|
CameraView(image: model.frame)
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user