I have a custom camera built using AVFoundation and Swift. When the camera launches it is initially zoomed in. After a second or so it zooms back out to normal. Im not sure why this is happening, I don’t modify the magnification at all and I don’t change the input camera. Maybe there is something off in my setup() function.
struct CameraPreview: UIViewRepresentable {
@EnvironmentObject var cameraModel : CameraViewModel
var size: CGSize
func makeUIView(context: Context) -> UIView {
let view = UIView(frame: CGRect(origin: .zero, size: size))
guard let preview = cameraModel.preview else { return view }
preview.frame = view.bounds
preview.videoGravity = .resizeAspectFill
view.layer.addSublayer(preview)
DispatchQueue.global(qos: .userInitiated).async {
if !self.cameraModel.session.isRunning {
self.cameraModel.session.startRunning()
}
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) { }
}
class CameraViewModel: NSObject, ObservableObject, AVCaptureFileOutputRecordingDelegate, AVCapturePhotoCaptureDelegate {
@Published var session = AVCaptureSession()
@Published var alert = false
@Published var output = AVCaptureMovieFileOutput()
@Published var preview: AVCaptureVideoPreviewLayer!
@Published var isRecording: Bool = false
@Published var recordedURLs: [URL] = []
@Published var previewURL: URL?
@Published var showPreview: Bool = false
@Published var recordedDuration: CGFloat = 0
@Published var maxDuration: CGFloat = 25
@Published var capturedImage: UIImage?
@Published var photoOutput = AVCapturePhotoOutput()
@Published var flashMode: AVCaptureDevice.TorchMode = .off
var currentCameraPosition: AVCaptureDevice.Position = .back
@Published var photoMode: Bool = true
@Published var isVideoFlashOn: Bool = false
override init() {
super.init()
self.checkPermission()
self.preview = AVCaptureVideoPreviewLayer(session: session)
self.preview.videoGravity = .resizeAspectFill
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
}
func checkPermission(){
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
checkAudioPermission()
return
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { (status) in
if status {
self.checkAudioPermission()
}
}
case .denied:
self.alert.toggle()
return
default:
return
}
}
func checkAudioPermission() {
switch AVCaptureDevice.authorizationStatus(for: .audio) {
case .authorized:
setUp()
return
case .notDetermined:
AVCaptureDevice.requestAccess(for: .audio) { (audioStatus) in
if audioStatus {
self.setUp()
}
}
case .denied:
self.alert.toggle()
return
default:
return
}
}
func setUp(){
do {
self.session.beginConfiguration()
let cameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)
let videoInput = try AVCaptureDeviceInput(device: cameraDevice!)
let audioDevice = AVCaptureDevice.default(for: .audio)
let audioInput = try AVCaptureDeviceInput(device: audioDevice!)
if self.session.canAddInput(videoInput) && self.session.canAddInput(audioInput){
self.session.addInput(videoInput)
self.session.addInput(audioInput)
}
if self.session.canAddOutput(self.output){
self.session.addOutput(self.output)
}
if self.session.canAddOutput(self.photoOutput) {
self.session.addOutput(self.photoOutput)
}
self.session.commitConfiguration()
}
catch {
print(error.localizedDescription)
}
}
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
}
}