Implement an ImagePicker in SwiftUI
Choose from your library or take a photo, all in SwiftUI
Step 1. How To Create Your SwiftUI Project
In Xcode, go to File → New → Project → Single View App → Next → Select User Interface → SwiftUI → Next → Select your desired project location → Done.
Step 2. ContentView.swift
The default SwiftUI(ContentView)
file will come up with the following code:
import SwiftUI
struct ContentView: View {var body: some View {
Text(”Hello World!”)
}
}struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
On the right-hand side, you can see the preview of the UI.
If you’re not able to see the preview, go to the Adjust Editor option, and select Canvas (or press option+CMD+enter
). After that, make sure the canvas is showing the UI preview.
Step 3. Creating a User Interface
Inside the ContentView
body we will be doing the following things:
- Define the
NavigationView
and give thenavigationBarTitle
. - Define the
VStack
. - Inside
VStack
, we have to define anImage
where we will display the selected image and aButton
. By clicking on this button, we will open up theImagePicker
.
So, our code will look something like this:
import SwiftUIstruct Demo: View {
var body: some View {
//MARK: Step 1: Define the NavigationView and give the navigationBarTitle
NavigationView{
//MARK: Step 2: Define the VStack
VStack {
//MARK: Define the Image
Image(systemName: “cloud”)
.resizable()
.scaledToFit()
.padding()
.foregroundColor(Color.orange)
//MARK: Define the Button
Button(“Open Camera”){
//Button Action Goes here
}.padding()
.foregroundColor(Color.white)
.background(Color.orange)
.cornerRadius(10)
}
.navigationBarTitle(Text(“Camera”))
}
}
}struct Demo_Previews: PreviewProvider {
static var previews: some View {
Demo()
}
}
Now we are done with our UI. Next, we have to implement the UIImagePickerController
.
Step 4. Creating a UIImagePickerController
Now the question is: “How are you going to show a UIImagePickerController
?” So, to display a UIImagePickerController
, we are going to use the UIViewControllerRepresentable
protocol.
struct ImagePicker : UIViewControllerRepresentable {}
Now, we have to implement the protocol methods, which are updateUIViewController
, makeCoordinator
, and makeUIViewController
.
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>)
{
//Update UIViewcontrolleer Method
}func makeCoordinator(){//Make Coordinator which will commnicate with the ImagePickerViewController
}func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>)
{
// Create UIViewController which we will display inside the View of the UIViewControllerRepresentable}
Since we have implemented all the methods of the protocol UIViewControllerRepresentable
, let’s create an ImagePickerViewController
inside the makeUIViewController
method.
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController
{
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
Step 5. Creating an ImagePickerCordinator
Now we have to create a coordinator that can communicate between the UIViewControllerRepresentable
and the ImagePickerViewController
delegate methods.
So, we will create a new class, ImagePickerCordinator
, that will implement the protocol UINavigationControllerDelegate
and UIImagePickerControllerDelegate
, and will implement the methods required by these protocols.
The ImagePickerCordinator
will look something like this:
class ImagePickerCordinator : NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate{var image : Image?//Selected Image
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
image = Image(uiImage: uiImage)
}//Image selection got cancel
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
}
}
Now, if the user selects an image, we have to notify our ContentView
to show the selected image.
For that, we will use the concept of the @Binding
and @State
. We will create two Binding
variables named image
and isShown
, so now our ImagePickerCordinator
will look like this:
class ImagePickerCordinator : NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate{@Binding var isShown : Bool
@Binding var image : Image?init(isShown : Binding<Bool>, image: Binding<Image?>) {
_isShown = isShown
_image = image
}//Selected Image
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImageimage = Image(uiImage: uiImage)
isShown = false}//Image selection got cancel
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isShown = false
}}
Now that our coordinator is ready to communicate, let’s make the changes into the UIViewControllerRepresentable
makeCoordinator()
function.
func makeCoordinator() -> ImagePickerCordinator {
return ImagePickerCordinator(isShown: $isShown, image: $image)
}
To pass the binding
variables in ImagePickerCordinator
, we will create these two variables in the UIViewControllerRepresentable
. Now the UIViewControllerRepresentable
file will look something like this:
struct ImagePicker : UIViewControllerRepresentable { @Binding var isShown : Bool
@Binding var image : Image?func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {}func makeCoordinator() -> ImagePickerCordinator {
return ImagePickerCordinator(isShown: $isShown, image: $image)
}func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
}
Step 6. Creating a PhotoCaptureView
Whenever the user clicks on the Button
in the ContentView
, we want to display an imagePicker
inside the sheet or modal.
For that, we will have to create a new CustomView
, which we can name PhotoCaptureView
, which will be calling the ImagePicker
. It is a UIViewControllerRepresentable
so it will look something like this:
import SwiftUIstruct PhotoCaptureView: View { @Binding var showImagePicker : Bool
@Binding var image : Image?
var body: some View {
ImagePicker(isShown: $showImagePicker, image: $image)
}
}struct PhotoCaptureView_Previews: PreviewProvider {
static var previews: some View {
PhotoCaptureView(showImagePicker: .constant(false), image: .constant(Image(“”)))
}
}
Final Step 7. Implement ImagePicker in ContentView
Inside the contentView
, we just have to create two @State
variables, named showImagePicker
and image
. This will create a sheet
or modal
and calls the CustomView
, i.e. PhotoCaptureView
, so our ContentView
code will look like this:
import SwiftUIstruct ContentView: View {
@State private var showImagePicker : Bool = false
@State private var image : Image? = nil
var body: some View {
NavigationView{
VStack {
image?.resizable().scaledToFit()
Button(“Open Camera”){
self.showImagePicker = true
}.padding()
.foregroundColor(Color.white)
.background(Color.purple)
.cornerRadius(10)
}.sheet(isPresented: self.$showImagePicker)
{
PhotoCaptureView(showImagePicker: self.$showImagePicker, image: self.$image)
}
.navigationBarTitle(Text(“Camera”))
}
}
}struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}