imaginary-cloud / CameraManager

Simple Swift class to provide all the configurations you need to create custom camera view in your app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CameraManager with SwiftUI?

Vweston opened this issue · comments

General Question about using CameraManager with SwiftUI. Is there an example of how to do this. I’m trying to figure it out, but still in a very early learning curve. Any help would be appreciated.

is there also a way to manually rotate the camera image &/or flip the camera image?

It works fine with UIViewControllerRepresentable. Here is an example that will attach an UIImage to the binding you pass.

To use it, create a view, your SwiftUI view where you want to have the CameraView. Your view needs to have a @State that holds the output UIImage and another @State that holds an instance of the Camera Manager.

So, in your body:

VStack {
                    if let cameraManager = self.cameraManager  {
                        CameraView(image: self.$capturedImage, cameraManager: cameraManager)
                    } else {
                        EmptyView()
                    }
                }.onAppear{
                    self.cameraManager = CameraManager()
                }.onDisappear{
                    self.cameraManager?.stopCaptureSession()
                    self.cameraManager = nil
                }

Use onAppear&onDisappear to init the CameraManager and shut off the camera afterwards. That's why I keep CameraManager as a @State. If you don't do that, you will have a greed dot on the top right corner of your screen indicating camera use and your users may think that you are secretly recording them.

struct CameraView : UIViewControllerRepresentable {
  
    @Binding var image : UIImage?
    let cameraManager : CameraManager?

    func makeUIViewController(context: Context) -> CMViewController {
        let vc = CMViewController(camera: .front, coordinator: context.coordinator)
        return vc
    }
    func updateUIViewController(_ uiViewController: CMViewController, context: Context) {
        print("Updated")
      
    }
    func makeCoordinator() -> Coordinator {
        //
        let coordinator = Coordinator(cameraManager : self.cameraManager ?? CameraManager())
         
        
        return coordinator
    }
    

    class Coordinator : NSObject {
        init(cameraManager: CameraManager) {
            self.cameraManager = cameraManager
        }
        
        let cameraManager : CameraManager
    }
    
    class CMViewController : UIViewController {

        let coordinator : Coordinator
        
        init(camera :  CameraDevice, coordinator : Coordinator) {
            self.coordinator = coordinator

            super.init(nibName: nil, bundle: nil)
            self.setCamera(camera)
        }
        func setCamera(_ camera : CameraDevice ){
            self.coordinator.cameraManager.cameraDevice = camera
            self.coordinator.cameraManager.writeFilesToPhoneLibrary = false
            
           
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        override func viewDidLoad() {
            self.coordinator.cameraManager.addLayerPreviewToView(self.view, newCameraOutputMode: .stillImage) {
                print("CMViewController DONE")
            }
        }
    }
    
}

Thank you Mertol Kasanan, that worked. It would have taken me quite awhile to figure all of that out. Saved me a lot of trial & error. Much appreciated.

Hi @mrtksn! I followed your code example, and I noticed a capture delay issue. If I switch between cameras and then capture a photo, it has a delay of about 2-3 seconds until the capture callback returns. After that, every time I switch the camera direction it adds to the delay.

Any idea why?

Found the reason why #114 (comment)