Damiano Miazzi
Damiano Miazzi

Reputation: 2335

New PhotosPicker in SwiftUI can open camera instead of the photoLibrary

is there any way to make the new PhotosPicker open the camera instead of opening the photoLibrary, I remember in the old UIImagePickerController there was this option user could choose in the picker if use camera or select from picture.


ImagePikerCircular(im: im, dataImage: $dataImage)
            .overlay(alignment: .bottomTrailing) {
                PhotosPicker(selection: $im.imageSelection,
                             matching: .images,
                             photoLibrary: .shared()) {
                    Image(systemName: "pencil.circle.fill")
                        .symbolRenderingMode(.multicolor)
                        .font(.system(size: 30))
                        .foregroundColor(.accentColor)
                }
                .buttonStyle(.borderless)
                .photosPickerStyle(.presentation)
            }

Upvotes: 5

Views: 3301

Answers (1)

Javier Galera
Javier Galera

Reputation: 166

No, there is no way to open the camera using the PhotosPicker, you will need to create your own selection dialog and when the user taps the camera, open the old UIImagePickerController, you can create a UIViewControllerRepresentable like this:

struct CameraPickerView: UIViewControllerRepresentable {
    
    private var sourceType: UIImagePickerController.SourceType = .camera
    private let onImagePicked: (UIImage) -> Void
    
    @Environment(\.presentationMode) private var presentationMode
    
    public init(onImagePicked: @escaping (UIImage) -> Void) {
        self.onImagePicked = onImagePicked
    }
    
    public func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.sourceType = self.sourceType
        picker.delegate = context.coordinator
        return picker
    }
    
    public func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
    
    public func makeCoordinator() -> Coordinator {
        Coordinator(
            onDismiss: { self.presentationMode.wrappedValue.dismiss() },
            onImagePicked: self.onImagePicked
        )
    }
    
    final public class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        
        private let onDismiss: () -> Void
        private let onImagePicked: (UIImage) -> Void
        
        init(onDismiss: @escaping () -> Void, onImagePicked: @escaping (UIImage) -> Void) {
            self.onDismiss = onDismiss
            self.onImagePicked = onImagePicked
        }
        
        public func imagePickerController(_ picker: UIImagePickerController,
                                          didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let image = info[.originalImage] as? UIImage {
                self.onImagePicked(image)
            }
            self.onDismiss()
        }
        public func imagePickerControllerDidCancel(_: UIImagePickerController) {
            self.onDismiss()
        }
    }
}

Then, you can present the picker with a fullScreenCover:

.fullScreenCover(isPresented: $showCameraPicker) {
    CameraPickerView() { image in
        // Do what you want with your image.
    }
}

source

Upvotes: 7

Related Questions