I've been trying to create a custom camera for several weeks. Been trying different tutorials but nothing seem to work. Now I feel like I have a good structure of the code yet after giving permission to use the camera on my physical device I just end up with a white screen. Any Ideas what the problem might be?
Here is my code:
import SwiftUI
import FirebaseCore
@main
struct FirebaseAuthYoutubeApp: App {
@StateObject var viewModal = AuthViewModel()
init() {
FirebaseApp.configure()
}
var body: some Scene {
WindowGroup {
/* ContentView()
.environmentObject(viewModal)
*/
CameraView2()
}
}
}
import SwiftUI
import AVFoundation
import UIKit
struct CamerVIEW2Kavsoft: View {
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
struct CamerVIEW2Kavsoft_Previews: PreviewProvider {
static var previews: some View {
CameraView2()
}
}
struct CameraView2: View {
@StateObject var camera = cameraModel()
var body: some View{
ZStack{
//Going to be the camera preview...
CameraPreview(camera: camera)
.ignoresSafeArea(.all, edges: .all)
VStack{
if camera.isTaken {
HStack{
Spacer()
Button(action: camera.retaTake, label: {
Image(systemName: "arrow.triangle.2.circlepath.camera")
.foregroundColor(.black)
.padding()
.background(Color.white)
.clipShape(Circle())
})
.padding(.trailing,10)
}
}
Spacer()
HStack {
// if taken showing save and again take button
if camera.isTaken {
Button(action: {if !camera.isSaved{camera.savePic()}}, label: {
Text(camera.isSaved ? "Saved" : "Save")
.foregroundColor(.black)
.fontWeight(.semibold)
.padding(.vertical,10)
.padding(.horizontal,20)
.background(Color.white)
.clipShape(Capsule())
})
.padding(.leading)
Spacer()
} else {
Button(action: {camera.takePic()}, label: {
ZStack{
Circle()
.fill(Color.white)
.frame(width: 65, height: 65)
Circle()
.stroke(Color.white, lineWidth: 2)
.frame(width: 75, height: 75)
}
})
}
}
.frame(height: 75)
}
}
.onAppear(perform: {
camera.Check()
})
}
}
//Camera Model...
class cameraModel: NSObject, ObservableObject, AVCapturePhotoCaptureDelegate {
@Published var isTaken = false
@Published var session = AVCaptureSession()
@Published var alert = false
// Since wew going to read pic data...
@Published var output = AVCapturePhotoOutput()
// preview
@Published var preview : AVCaptureVideoPreviewLayer!
@Published var isSaved = false
@Published var picData = Data(count: 0)
func Check() {
//first checking cameras got permission..
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
//setting up session
setUp()
return
case .notDetermined:
// retesting for permission...
AVCaptureDevice.requestAccess(for: .video) { (status) in
if status {
self.setUp()
}
}
case .denied:
self.alert.toggle()
return
default:
return
}
}
func setUp() {
// setting up camera
do {
// setting configs..
self.session.beginConfiguration()
if let device = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: .back) {
do {
let input = try AVCaptureDeviceInput(device: device)
//checking and adding to session
if self.session.canAddInput(input) {
self.session.addInput(input)
}
} catch {
print(error.localizedDescription)
}
// Same for outputs...
if self.session.canAddOutput(self.output) {
self.session.addOutput(self.output)
}
self.session.commitConfiguration()
}
}catch {
print(error.localizedDescription)
}
}
// take and retake functions...
func takePic(){
DispatchQueue.global(qos: .background).async {
self.output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
self.session.stopRunning()
DispatchQueue.main.async {
withAnimation{self.isTaken.toggle()}
// clearing
self.isSaved = false
}
}
}
func retaTake() {
DispatchQueue.global(qos: .background).async {
self.session.startRunning()
DispatchQueue.main.async {
withAnimation{self.isTaken.toggle()}
}
}
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if error != nil{
return
}
print("pic taken...")
guard let imageData = photo.fileDataRepresentation() else {return}
self.picData = imageData
}
func savePic() {
let image = UIImage(data: self.picData)!
// saving Image...
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
self.isSaved = true
print("saved succeded ")
}
}
//Setting view for preview...
struct CameraPreview: UIViewRepresentable {
@ObservedObject var camera : cameraModel
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: UIScreen.main.bounds)
camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
camera.preview.frame = view.frame
// Your own properties...
camera.preview.videoGravity = .resizeAspectFill
view.layer.addSublayer(camera.preview)
//starting session
camera.session.startRunning()
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
This is my permissions info.plist setting:
Earlier I got a fatal error on the let
input =
try
AVCaptureDeviceInput(device: device)
line in my setUp function so I tried to use optional binding instead but no luck.