The PHPickerViewController class is the new system picker that allows you to get access to images and videos from the user’s photo library.
PHPickerViewController is an alternative to UIImagePickerController with ability to select more than one image at once. UIImagePickerController was a good choice before iOS 14.0 as simple image picker.
Contrarily to the UIImagePickerController, PHPicker provides a better privacy and does not require to ask for user consent so it can be used.
UIKit
import UIKit
import PhotosUI
class PhotosUIViewController: UIViewController {
lazy var addButton: UIButton = {
let v = UIButton(type: .system)
v.setTitle("Add", for: .normal)
v.translatesAutoresizingMaskIntoConstraints = false
v.addTarget(self, action: #selector(handleAdd), for: .touchUpInside)
return v
}()
lazy var stackView: UIStackView = {
let v = UIStackView(arrangedSubviews: [addButton])
v.translatesAutoresizingMaskIntoConstraints = false
v.axis = .vertical
v.distribution = .fillProportionally
v.spacing = 8
v.alignment = .fill
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
stackView.topAnchor.constraint(equalTo: view.topAnchor),
stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
extension PhotosUIViewController: PHPickerViewControllerDelegate {
@objc func handleAdd() {
var config = PHPickerConfiguration()
config.selectionLimit = 0
config.filter = PHPickerFilter.images
let pickerViewController = PHPickerViewController(configuration: config)
pickerViewController.delegate = self
self.present(pickerViewController, animated: true, completion: nil)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
for result in results {
result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { [weak self] (object, error) in
if let image = object as? UIImage {
DispatchQueue.main.async { [weak self] in
self?.stackView.addArrangedSubview(UIImageView(image: image))
}
}
})
}
}
}
SwiftUI
You can use following snippet starting from iOS 16.0. To use PHPicker on 14.0 iOS version or above you have to wrap it in UIViewControllerRepresentable.
import SwiftUI
import PhotosUI
struct PhotoView: View {
@State var photoItems = [PhotosPickerItem]()
@State var selectedPhotos = [UIImage]()
var body: some View {
VStack {
if !selectedPhotos.isEmpty {
ScrollView(showsIndicators: false) {
ForEach(selectedPhotos, id: \.self) { photo in
Image(uiImage: photo)
.resizable()
.scaledToFit()
.frame(width: 200, height: 200)
}
}
}
PhotosPicker(selection: $photoItems, maxSelectionCount: 0, matching: .images) {
Label("Select photos", systemImage: "photo")
}
.onChange(of: photoItems) { newItems in
newItems.forEach { item in
Task {
guard let data = try? await item.loadTransferable(type: Data.self) else { return }
guard let image = UIImage(data: data) else { return }
selectedPhotos.append(image)
}
}
}
}
}
}