Skip to content
DeveloperMemos

Using PHPickerViewController in SwiftUI with UIViewControllerRepresentable

SwiftUI, PHPickerViewController, UIViewControllerRepresentable2 min read

The PHPickerViewController is a powerful class introduced in iOS 14 that allows you to provide an image and video picker interface in your app. It provides a consistent and customizable way for users to select media from their photo library. While SwiftUI does not have a direct implementation of PHPickerViewController, you can easily use it in your SwiftUI app by leveraging the UIViewControllerRepresentable protocol. This article will guide you through the process of integrating PHPickerViewController into your SwiftUI project.

What is UIViewControllerRepresentable?

UIViewControllerRepresentable is a protocol in SwiftUI that allows you to wrap a UIKit view controller and use it as a SwiftUI view. It acts as a bridge between the two frameworks, enabling you to incorporate UIKit components seamlessly into your SwiftUI interface. By conforming to this protocol, you can create a custom SwiftUI view that encapsulates the functionality of a UIKit view controller.

Creating a Wrapper for PHPickerViewController

To use PHPickerViewController in your SwiftUI app, start by creating a new struct that conforms to UIViewControllerRepresentable. This struct will act as a wrapper for the PHPickerViewController:

1import SwiftUI
2import PhotosUI
3
4struct PHPickerViewControllerWrapper: UIViewControllerRepresentable {
5 typealias UIViewControllerType = PHPickerViewController
6
7 func makeUIViewController(context: Context) -> PHPickerViewController {
8 let configuration = PHPickerConfiguration()
9 configuration.filter = .images
10 configuration.selectionLimit = 1
11
12 let picker = PHPickerViewController(configuration: configuration)
13 picker.delegate = context.coordinator
14
15 return picker
16 }
17
18 func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}
19
20 func makeCoordinator() -> Coordinator {
21 Coordinator()
22 }
23
24 class Coordinator: NSObject, PHPickerViewControllerDelegate {
25 func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
26 guard let itemProvider = results.first?.itemProvider else { return }
27
28 if itemProvider.canLoadObject(ofClass: UIImage.self) {
29 itemProvider.loadObject(ofClass: UIImage.self) { image, error in
30 if let image = image as? UIImage {
31 // Do something with the selected image
32 }
33 }
34 }
35 }
36 }
37}

In the code above, we define a struct PHPickerViewControllerWrapper that conforms to UIViewControllerRepresentable. We specify the associated type UIViewControllerType as PHPickerViewController. In the makeUIViewController method, we create an instance of PHPickerViewController and configure it with a PHPickerConfiguration. Here, we set the filter to images and limit the selection to one item. We also assign the delegate to the coordinator.

The makeCoordinator method returns an instance of the coordinator class, which adopts the PHPickerViewControllerDelegate protocol. Inside the coordinator, we handle the didFinishPicking method and retrieve the selected item provider. If the item provider can load an object of type UIImage, we extract the image and perform the necessary actions.

Using the Wrapper in SwiftUI View

Once we have the wrapper for PHPickerViewController, we can use it in our SwiftUI view like any other SwiftUI component. Here's an example of how you can integrate it into your view:

1import SwiftUI
2
3struct ContentView: View {
4 @State private var showPicker = false
5
6 var body: some View {
7 VStack {
8 Button(action: {
9 showPicker.toggle()
10 }) {
11 Text("Select Image")
12 }
13 .sheet(isPresented: $showPicker) {
14 PHPickerViewControllerWrapper()
15 }
16 }
17 }
18}

In the code above, we create a button that toggles the showPicker state when tapped. We then use the .sheet modifier to present the PHPickerViewControllerWrapper as a sheet when showPicker is true. This will display the PHPickerViewController and allow the user to select an image.

Customizing the PHPickerViewController

You can customize the appearance and behavior of the PHPickerViewController by modifying the PHPickerConfiguration object in the makeUIViewController method of the wrapper. The configuration allows you to set options such as filtering media types, selecting multiple items,customizing the navigation bar, and more. You can explore the PHPickerConfiguration documentation for a comprehensive list of available options.

Handling Selected Media

Once the user selects media using the PHPickerViewController, you can handle the selected media in the coordinator's didFinishPicking method. In the example code, we extract the selected image as a UIImage. From there, you can perform any necessary operations on the selected media, such as displaying it in your app, uploading it to a server, or applying filters.

Remember to handle potential errors and handle other types of media, such as videos, if required. The PHPickerResult object provides access to the itemProvider, allowing you to check its type and load the corresponding object.

Wrapping Up

Using UIViewControllerRepresentable opens up a world of possibilities when it comes to incorporating UIKit components into your SwiftUI projects. It allows you to combine the best of both worlds, utilizing the rich ecosystem of UIKit while enjoying the declarative nature of SwiftUI.

Now that you have a solid understanding of integrating PHPickerViewController in SwiftUI with UIViewControllerRepresentable, you can start incorporating this powerful media picker into your own apps and enhance the user experience!