Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to open the ImagePicker in SwiftUI?

I need to open an image picker in my app using SwiftUI, how can I do that?

I thought about using the UIImagePickerController, but I don't know how to do that in SwiftUI.

like image 598
Shahar Avatar asked Jun 09 '19 15:06

Shahar


People also ask

How do I open an image picker in SwiftUI?

You need to wrap UIImagePickerController in a struct implementing UIViewControllerRepresentable . Here's a simple view to test it: The picker is displayed in a sheet. the selected image appears without any sort of animation, and replaces the Show image picker button.

How do I use sheets in SwiftUI?

To use a sheet, give it something to show (some text, an image, a custom view, etc), add a Boolean that defines whether the detail view should be showing, then attach it to your main view as a modal sheet. Important: If you're targeting iOS 14 or below, you should use @Environment(\.


1 Answers

You need to wrap UIImagePickerController in a struct implementing UIViewControllerRepresentable.

For more about UIViewControllerRepresentable, please check this amazing WWDC 2019 talk:

Integrating SwiftUI

struct ImagePicker: UIViewControllerRepresentable {      @Environment(\.presentationMode)     private var presentationMode      let sourceType: UIImagePickerController.SourceType     let onImagePicked: (UIImage) -> Void      final class Coordinator: NSObject,     UINavigationControllerDelegate,     UIImagePickerControllerDelegate {          @Binding         private var presentationMode: PresentationMode         private let sourceType: UIImagePickerController.SourceType         private let onImagePicked: (UIImage) -> Void          init(presentationMode: Binding<PresentationMode>,              sourceType: UIImagePickerController.SourceType,              onImagePicked: @escaping (UIImage) -> Void) {             _presentationMode = presentationMode             self.sourceType = sourceType             self.onImagePicked = onImagePicked         }          func imagePickerController(_ picker: UIImagePickerController,                                    didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {             let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage             onImagePicked(uiImage)             presentationMode.dismiss()          }          func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {             presentationMode.dismiss()         }      }      func makeCoordinator() -> Coordinator {         return Coordinator(presentationMode: presentationMode,                            sourceType: sourceType,                            onImagePicked: onImagePicked)     }      func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {         let picker = UIImagePickerController()         picker.sourceType = sourceType         picker.delegate = context.coordinator         return picker     }      func updateUIViewController(_ uiViewController: UIImagePickerController,                                 context: UIViewControllerRepresentableContext<ImagePicker>) {      }  } 

Here's a simple view to test it:

  • The picker is displayed in a sheet
  • the selected image appears without any sort of animation, and replaces the Show image picker button
struct ContentView: View {      @State var showImagePicker: Bool = false     @State var image: Image? = nil      var body: some View {         ZStack {             VStack {                 Button(action: {                     self.showImagePicker.toggle()                 }) {                     Text("Show image picker")                 }                 image?.resizable().frame(width: 100, height: 100)             }             .sheet(isPresented: $showImagePicker) {                 ImagePicker(sourceType: .photoLibrary) { image in                     self.image = Image(uiImage: image)                 }             }         }     } } 

I hope this helps as a starting point!

I'm sure Apple will make this easier to do once SwiftUI is out of beta.

enter image description here

Tested on Xcode 11.4

Bugs:

  • @JAHelia found a bug on the picker when sourceType is not the camera. You won't be able to drag down the sheet - I haven't been able to find a solution yet.
like image 69
Matteo Pacini Avatar answered Sep 22 '22 02:09

Matteo Pacini