How to open the ImagePicker in SwiftUI?

后端 未结 8 1315
生来不讨喜
生来不讨喜 2020-11-29 23:53

I need to open the ImagePicker 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 Swi

8条回答
  •  余生分开走
    2020-11-30 00:24

    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,
                 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) -> UIImagePickerController {
            let picker = UIImagePickerController()
            picker.sourceType = sourceType
            picker.delegate = context.coordinator
            return picker
        }
    
        func updateUIViewController(_ uiViewController: UIImagePickerController,
                                    context: UIViewControllerRepresentableContext) {
    
        }
    
    }
    

    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.

    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.

提交回复
热议问题