19
Aug
2021
SwiftUI Image Picker
Reading time: 1 min
This recipe shows how to add an image picker to your SwiftUI app. You'll do this by wrapping a UIKit UIImagePickerController
in a UIViewControllerRepresentable
.
The end result looks like this:
This recipe is a part of our Road to DigitalSignatureView series, which explores various components vital to functioning of our SwiftUIDigitalSignature component.
OK, here's the code:
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) private var presentationMode // allows you to dismiss the image picker overlay
@Binding var selectedImage: UIImage // selected image binding
@Binding var didSet: Bool // tells if the view was set or cancelled
var sourceType = UIImagePickerController.SourceType.photoLibrary
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let imagePicker = UIImagePickerController()
imagePicker.navigationBar.tintColor = .clear
imagePicker.allowsEditing = false
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController,
context: UIViewControllerRepresentableContext<ImagePicker>) { }
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let control: ImagePicker
init(_ control: ImagePicker) {
self.control = control
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
control.selectedImage = image
control.didSet = true
}
control.presentationMode.wrappedValue.dismiss()
}
}
}
Then, you can just wrap it in a popover
and present it in your View
:
struct SignatureImageView: View {
@Binding var isSet: Bool
@Binding var selection: UIImage
@State private var showPopover = false
var body: some View {
Button(action: {
showPopover.toggle()
}) {
if isSet {
Image(uiImage: selection)
.resizable()
.frame(maxHeight: maxHeight)
} else {
ZStack {
Color.white
Text("Choose signature image")
.font(.system(size: 18))
.foregroundColor(.gray)
}.frame(height: maxHeight)
.overlay(RoundedRectangle(cornerRadius: 4)
.stroke(Color.gray))
}
}.popover(isPresented: $showPopover) {
ImagePicker(selectedImage: $selection, didSet: $isSet)
}
}
}