6.5. Using Gallery: PHPicker

PHPicker is a view controller that provides the user interface for choosing assets from the photo library. We use this view controller to browse the local image assets, select the chosen image(s), and retrieve the image(s). It is a highly configurable and scalable tool and fairly easy to use. We need to import PhotosUI library to use the tool.

So, let's open AddExpenseViewController.swift file. We will write codes in pickPhotoFromGallery() method. We also need to adopt PHPickerViewControllerDelegate protocol using the extension keyword. Let's add the following code in AddExpenseViewController.swift file:

//
//  AddExpenseViewController.swift
//  App6
//
//  Created by Sakib Miazi on 5/18/23.
//

import UIKit
import PhotosUI //MARK: importing the library to use PHPicker...

class AddExpenseViewController: UIViewController {
    //codes omitted...
    
    //MARK: variable to store the picked Image...
    var pickedImage:UIImage?
    
    //Codes omitted...
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
       //codes omitted...
        
        //MARK: adding menu to buttonTakePhoto...
        addExpenseScreen.buttonTakePhoto.menu = getMenuImagePicker()
        
        //codes omitted...
    }
    
    //codes omitted...
    
    func getMenuImagePicker() -> UIMenu{
        var menuItems = [
            UIAction(title: "Camera",handler: {(_) in
                self.pickUsingCamera()
            }),
            UIAction(title: "Gallery",handler: {(_) in
                self.pickPhotoFromGallery()
            })
        ]
        
        return UIMenu(title: "Select source", children: menuItems)
    }
    
    //codes omitted...
    
    //MARK: pick Photo using Gallery...
    func pickPhotoFromGallery(){
        var configuration = PHPickerConfiguration()
        configuration.filter = PHPickerFilter.any(of: [.images])
        configuration.selectionLimit = 1
        
        let photoPicker = PHPickerViewController(configuration: configuration)
        
        photoPicker.delegate = self
        present(photoPicker, animated: true, completion: nil)
    }
    //codes omitted...

}

//MARK: adopting required protocols for PHPicker...
extension AddExpenseViewController:PHPickerViewControllerDelegate{
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        dismiss(animated: true)
        
        print(results)
        
        let itemprovider = results.map(\.itemProvider)
        
        for item in itemprovider{
            if item.canLoadObject(ofClass: UIImage.self){
                item.loadObject(ofClass: UIImage.self, completionHandler: { (image, error) in
                    DispatchQueue.main.async{
                        if let uwImage = image as? UIImage{
                            self.addExpenseScreen.buttonTakePhoto.setImage(
                                uwImage.withRenderingMode(.alwaysOriginal),
                                for: .normal
                            )
                            self.pickedImage = uwImage
                        }
                    }
                })
            }
        }
    }
}

Here,

  • We are importing the library PhotosUI using import keyword.

  • Then, inside the class, we keep a variable pickedImage of type UIImage to store the picked image.

  • Inside the pickPhotoFromGallery() method:

    • We create a configuration for the picker.

    • We are saying that we want to pick the images from the Gallery. You can modify it to pick Videos, GIFs, etc.

    • We write configuration.selectionLimit = 1 to say that only one image can be selected from the Gallery. If you have used texting apps like WhatsApp or even Messages, you can see that you can select multiple images together and send them together in a message. PHPicker allows you to build similar functionalities. For our case, we need to select only one image.

    • Then we create the instance of PHPickerViewController, photoPickerwith the configuration we created.

    • Then we set the photoPicker's delegate to self to enable this screen to handle the PHPicker.

    • Then we present the photoPicker on the screen.

  • Adopting PHPickerViewControllerDelegate protocol:

    • We must implement didFinishPicking method to handle the results. results contain the images we picked using the photoPicker.

    • If you directly print the results, you should see something like the following:

    • Notice that it is a file structure. It creates a package of selected images in the 'itemProvider' directory. For example, I selected the "public.jpeg" image from the gallery, and the photoPicker sent the image with this package.

    • Now, between line 71 through 85, we iterate through all the images inside the package and asynchronously (DispatchQueue) fetch the images and deal with them. Since we have only one image, we set the image to pickedImage.

    • You might get confused by seeing:

    • Here, we are setting the image rendering mode to alwaysOriginal for setting the image for buttonTakePhoto. We set a specific rendering mode because iOS sets a tint on top of the images inside a button. That would ruin the original image. To remove the tinting effect, we set the rendering mode to alwaysOriginal. Try removing the rendering mode, and see the tinting effect.

Alright! We are done setting up the PHPicker, and now it's time to test the app.

Last updated

Was this helpful?