Presenting PHPicker with SwiftUI

Does someone have an example of displaying a PHPicker from a SwifUI App?
Answered by DTS Engineer in 744921022

Hello,

There is now a native PhotosPicker for SwiftUI, I recommend that you use that instead of the representable container provided in the "Accepted Reply".

I just asked myself the same question. I had expected the sample code from PHPicker session would have shown this.

There are good instructions here https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit that show how to interface SwiftUI with other UIKits.
Accepted Answer
Yes this will require a representable, here is a short example:

Code Block
struct ContentView: View {
    @State private var isPresented: Bool = false
    var body: some View {
        Button("Present Picker") {
            isPresented.toggle()
        }.sheet(isPresented: $isPresented) {
            let configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
            PhotoPicker(configuration: configuration, isPresented: $isPresented)
        }
    }
}
struct PhotoPicker: UIViewControllerRepresentable {
    let configuration: PHPickerConfiguration
    @Binding var isPresented: Bool
    func makeUIViewController(context: Context) -> PHPickerViewController {
        let controller = PHPickerViewController(configuration: configuration)
        controller.delegate = context.coordinator
        return controller
    }
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) { }
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    // Use a Coordinator to act as your PHPickerViewControllerDelegate
    class Coordinator: PHPickerViewControllerDelegate {
     
        private let parent: PhotoPicker
        
        init(_ parent: PhotoPicker) {
            self.parent = parent
        }
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            print(results)
            parent.isPresented = false // Set isPresented to false because picking has finished.
        }
    }
}

10
I have just tried to make it work with multi selection. This works in a ScrollView implementation. I have struggled to get it working in a TabView. Maybe someone will have it working.

Code Block swift
import SwiftUI
import PhotosUI
struct PhotoPicker: UIViewControllerRepresentable {
typealias UIViewControllerType = PHPickerViewController
@Binding var images: [UIImage]
var itemProviders: [NSItemProvider] = []
func makeUIViewController(context: Context) -> PHPickerViewController {
var configuration = PHPickerConfiguration()
configuration.selectionLimit = 10
configuration.filter = .images
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
}
func makeCoordinator() -> Coordinator {
return PhotoPicker.Coordinator(parent: self)
}
class Coordinator: NSObject, PHPickerViewControllerDelegate, UINavigationControllerDelegate {
var parent: PhotoPicker
init(parent: PhotoPicker) {
self.parent = parent
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
if !results.isEmpty {
parent.itemProviders = []
parent.images = []
}
parent.itemProviders = results.map(\.itemProvider)
loadImage()
}
private func loadImage() {
for itemProvider in parent.itemProviders {
if itemProvider.canLoadObject(ofClass: UIImage.self) {
itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
if let image = image as? UIImage {
self.parent.images.append(image)
} else {
print("Could not load image", error?.localizedDescription ?? "")
}
}
}
}
}
}
}


Hello,

There is now a native PhotosPicker for SwiftUI, I recommend that you use that instead of the representable container provided in the "Accepted Reply".

Presenting PHPicker with SwiftUI
 
 
Q