Home IOS Development Selecting photos with UIImagePickerController in Swift 5

Selecting photos with UIImagePickerController in Swift 5

0
Selecting photos with UIImagePickerController in Swift 5

[ad_1]

Are you in search of a video picker as properly? 🍿 Try my one other publish about choosing & enjoying video recordsdata in iOS.

A reusable picture picker class for iOS

So on this tutorial we’ll create a reusable class constructed on prime of UIKit in an effort to make picture choice extra nice in your apps, every thing written in Swift 5.

This text was impressed by my earlier try to resolve the picture choosing problem in a protocol oriented manner, however that article is these days just a little bit obsolated, plus I would not use that approach anymore.

Folks at all times be taught from the previous, so as an alternative of utilizing a protocol oriented method, this time I am going to merely go along with an ImagePicker class. No singletons, no additional library, only a small helper class that may be instantiated within the applicable place, to do it is job. 🌄

I am solely going to give attention to choosing edited photos, if you would like to make use of dwell pictures or films, you possibly can at all times customise the ImagePicker class, or create an summary one and implement subclasses for every media kind. I would accomplish that too. 😅

So let’s dive in, right here is my primary implementation, however you possibly can obtain an entire instance undertaking with video choosing as properly from The.Swift.Dev. tutorials repository on GitHub.

Privateness first!

These days privateness issues lots, so you must add two essential keys to your functions Information.plist file, in any other case you will find yourself with a horrible crash! ⚠️

Because you’d prefer to get some personal information, you must present an evidence message for the consumer (and for Apple) why the app is requesting digicam & photograph library entry. The NSCameraUsageDescription is for digicam and NSPhotoLibraryUsageDescription secret’s for photograph library entry. Each values ought to be a simple string that’ll clarify the consumer why you want his/her nude footage. Privateness is essential! 🔒

<key>NSCameraUsageDescription</key>
<string>This app needs to take footage.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs to make use of your pictures.</string>

Clearly if you would like to make use of pictures instantly taken from the digicam, however you do not need to entry the photograph library, you simply have so as to add the correct key. That is it now we’re able to do some precise coding. ⌨️

The anatomy of UIImagePickerController

The anatomy of a UIPickerController is kind of easy. Principally it is a common view controller, you simply should set just a few additional properties to make it work.

let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
pickerController.mediaTypes = ["public.image", "public.movie"]
pickerController.sourceType = .digicam

Permits modifying is a flag that signifies if the resizing & cropping interface ought to be introduced after deciding on & taking an image, if true you must use the .editedImage as an alternative of the .originalImage key – contained in the picker delegate – to get the correct picture from the picture information dictionary.

There are principally two sorts of media varieties accessible: photos and flicks. You will get the accessible media kind strings for every supply kind by calling a category methodology on the picker:

UIImagePickerController.availableMediaTypes(
    for: .digicam
)

There are 3 accessible supply varieties: .digicam, which is the digicam, and there are two different choices to get footage from the photograph library. The .photoLibrary enum case will provide you with full entry, however you possibly can restrict the choice scope just for the digicam roll for those who select .savedPhotosAlbum.

The delegate ought to implement each the UIImagePickerControllerDelegate and the UINavigationControllerDelegate protocols, nonetheless often my navigation controller delegate is simply an empty implementation. In the event you want additional navigation associated logic, you would possibly must create just a few strategies there as properly.

Awww, let’s simply put every thing collectively…

import UIKit

public protocol ImagePickerDelegate: class {
    func didSelect(picture: UIImage?)
}

open class ImagePicker: NSObject {

    personal let pickerController: UIImagePickerController
    personal weak var presentationController: UIViewController?
    personal weak var delegate: ImagePickerDelegate?

    public init(presentationController: UIViewController, delegate: ImagePickerDelegate) {
        self.pickerController = UIImagePickerController()

        tremendous.init()

        self.presentationController = presentationController
        self.delegate = delegate

        self.pickerController.delegate = self
        self.pickerController.allowsEditing = true
        self.pickerController.mediaTypes = ["public.image"]
    }

    personal func motion(for kind: UIImagePickerController.SourceType, title: String) -> UIAlertAction? {
        guard UIImagePickerController.isSourceTypeAvailable(kind) else {
            return nil
        }

        return UIAlertAction(title: title, model: .default) { [unowned self] _ in
            self.pickerController.sourceType = kind
            self.presentationController?.current(self.pickerController, animated: true)
        }
    }

    public func current(from sourceView: UIView) {

        let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        if let motion = self.motion(for: .digicam, title: "Take photograph") {
            alertController.addAction(motion)
        }
        if let motion = self.motion(for: .savedPhotosAlbum, title: "Digital camera roll") {
            alertController.addAction(motion)
        }
        if let motion = self.motion(for: .photoLibrary, title: "Picture library") {
            alertController.addAction(motion)
        }

        alertController.addAction(UIAlertAction(title: "Cancel", model: .cancel, handler: nil))

        if UIDevice.present.userInterfaceIdiom == .pad {
            alertController.popoverPresentationController?.sourceView = sourceView
            alertController.popoverPresentationController?.sourceRect = sourceView.bounds
            alertController.popoverPresentationController?.permittedArrowDirections = [.down, .up]
        }

        self.presentationController?.current(alertController, animated: true)
    }

    personal func pickerController(_ controller: UIImagePickerController, didSelect picture: UIImage?) {
        controller.dismiss(animated: true, completion: nil)

        self.delegate?.didSelect(picture: picture)
    }
}

extension ImagePicker: UIImagePickerControllerDelegate {

    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.pickerController(picker, didSelect: nil)
    }

    public func imagePickerController(_ picker: UIImagePickerController,
                                      didFinishPickingMediaWithInfo information: [UIImagePickerController.InfoKey: Any]) {
        guard let picture = information[.editedImage] as? UIImage else {
            return self.pickerController(picker, didSelect: nil)
        }
        self.pickerController(picker, didSelect: picture)
    }
}

extension ImagePicker: UINavigationControllerDelegate {

}

In the event you need not choose from a supply kind, issues are fairly simple, you possibly can merely current your picker view controller, deal with every thing within the delegate and you’re carried out. Nevertheless, if you could select from an enter supply, that includes just a little bit extra logic, particularly on iPads. 📱

I am utilizing a UIAlertController in an effort to compose a supply kind choice dialog. I am attempting so as to add 3 actions (based mostly on the choosing supply kind), however provided that the supply kind is on the market on that given gadget (e.g. .digicam just isn’t accessible within the simulator). You may test availability by: UIImagePickerController.isSourceTypeAvailable(kind).

Alert controllers wants just a few additional issues on iPads, that is why I am establishing the popoverPresentationController properties within the current methodology. It is often sufficient to set the sourceView and the sourceRect properties, however you may also customise arrow instructions. ⬅️➡️⬆️⬇️

It is at all times your process to test if the gadget is an iPad & set the correct supply view & rect if it is wanted, in any other case your app will crash on iPads. One other factor is that you must dismiss the UIPickerViewController after the picker did it is job! ⚠️

Time to say cheese! 🧀

The best way to use the picture picker class?

Nicely, now you’re able to take some footage. I’ve made a easy view controller to indicate you an actual fast instance. You solely want a UIImageView and a UIButton.

Now that is the code for the pattern view controller. Nothing magical, I simply cross the controller as a presentationController for the ImagePicker so it will have the ability to current the UIImagePickerController on prime of that. I separated the delegate from the presentation controller, as a result of generally it comes useful. 🤷‍♂️

class ViewController: UIViewController {

    @IBOutlet var imageView: UIImageView!

    var imagePicker: ImagePicker!

    override func viewDidLoad() {
        tremendous.viewDidLoad()

        self.imagePicker = ImagePicker(presentationController: self, delegate: self)
    }

    @IBAction func showImagePicker(_ sender: UIButton) {
        self.imagePicker.current(from: sender)
    }
}

extension ViewController: ImagePickerDelegate {

    func didSelect(picture: UIImage?) {
        self.imageView.picture = picture
    }
}

The ImagePickerDelegate delegate on this case is the most straightforward one I can think about. It simply offers the picked picture so that you’re prepared to make use of it. Nevertheless in some instances you would possibly want just a few more information from the picture picker.

If you wish to take this method one step additional, you possibly can create an summary class or a protocol that defines the essential performance and based mostly on which you could implement varied media picker controllers to suit your wants.

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here