Picking Two Different Images in the Same View Controller Using Imagepickercontroller in Swift

Picking two different images in the same view controller using imagePickerController in Swift

You only need one UIImagePickerController. You can keep a reference of the tapped view and when the user finish picking the image, you just need to cast the selected view as UIImageView and set its image property:

update: Xcode 11.5 • Swift 5.2 or later

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate ,UINavigationControllerDelegate {

@IBOutlet weak var imageView1: UIImageView!
@IBOutlet weak var imageView2: UIImageView!

var imagePicker = UIImagePickerController()
var selectedVew: UIView!

override func viewDidLoad() {
super.viewDidLoad()

imagePicker.delegate = self
imagePicker.sourceType = .savedPhotosAlbum
imagePicker.allowsEditing = false

[imageView1,imageView2].forEach {
$0?.isUserInteractionEnabled = true
$0?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(chooseImage)))
}
}

@objc func chooseImage(_ gesture: UITapGestureRecognizer) {
if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) {
selectedVew = gesture.view
present(imagePicker, animated: true)
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
(selectedVew as? UIImageView)?.image = info[.originalImage] as? UIImage
dismiss(animated: true)
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
}
}

How to display two images on two UIImageViews one View Controller, UIImagePickerController's?

What you observe is that when the user taps on any of the image views (wallpaperPhoto or profilePhoto), the UIImagePickerController always uses self as its delegate. Then, when the user picks an image, the delegate cannot distinguish any more which image view originally was tapped.

You could simply add a weak optional variable indicating the "active" tapped image view, and then set only it's image. Also, you can reduce the tap handler to a single function with a sender argument, which is the image view the user tapped on, and set the activeImageViewto this.

extension SettingProfileViewController:UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var activeImageView:UIImageView? = nil

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
activeImageView.image = image
}
dismiss(animated: true, completion: nil)
}


override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(SettingProfileViewController.handleSelect(_:))
profilePhoto.addGestureRecognizer(tapGesture)
profilePhoto.isUserInteractionEnabled = true

let wallTapGesture = UITapGestureRecognizer(target: self, action: #selector(SettingProfileViewController.handleSelect(_:)))
wallpaperPhoto.addGestureRecognizer(wallTapGesture)
wallpaperPhoto.isUserInteractionEnabled = true
}

@objc func handleSelect(sender:UIGestureRecognizer) {
guard let sendingImageView = sender.view as? UIImageView else {
print("Ooops, received this gesture not from an ImageView")
return
}
activeImageView = sendingImageView
let pickerController = UIImagePickerController() //открывает галерею
pickerController.delegate = self
present(pickerController, animated: true, completion: nil)
}

// ...

one UIImagePickerController for multiple UIImageViews in a single VC

You can make an enum to store the possible picker types (profile or ID picture).

enum PictureSelectionType {
case profilePicture
case idPicture
}
class DriverAplication: UIViewController {
var pictureSelectionType = PictureSelectionType.profilePicture

/// inside ViewDidLoad...
let profileImgTapGestur = UITapGestureRecognizer(target: self, action: #selector(DriverAplication.selectProfileImage))
driverPImg.addGestureRecognizer(profileImgTapGestur)

let passImgTapGestur = UITapGestureRecognizer(target: self, action: #selector(DriverAplication.selectIDImage))
passImg.addGestureRecognizer(passImgTapGestur)


@objc func selectProfileImage() {
/// remember what the picker should return
pictureSelectionType = .profilePicture

let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()

let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
present(pickerController, animated: true, completion: nil)

}
@objc func selectIDImage() {
/// remember what the picker should return
pictureSelectionType = .idPicture

let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()

let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
present(pickerController, animated: true, completion: nil)
}
}

extension DriverAplication: UINavigationControllerDelegate, UIImagePickerControllerDelegate {

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

var returnedImage: UIImage?
if let editedImg = info[.editedImage] as? UIImage {
returnedImage = editedImg
} else if let originalImg = info[.originalImage] as? UIImage {
returnedImage = originalImg
}

if let image = returnedImage { /// unwrap the image

/// read what the selection type is
if pictureSelectionType == .profilePicture {
driverPImg.image = image
} else { /// for ID picture
passImg.image = image
}
}

dismiss(animated: true, completion: nil)
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.dismiss(animated: true, completion: nil)
}
}

How to Set 2 different images using one UIImagePickerControllerDelegate?

You can create an enum for picker mode and check it when assigning the picked photo to its related property. - unknown case is optional.

private enum ImagePickerMode {
case coverPhoto
case profilePhoto
case unknown
}

By keeping it on the related controller as a variable, you can check which photo property should be updated.

private var imagePickerMode: ImagePickerMode = .unknown

If you change the method for changing photo as following, you may reduce the duplicate code.

private func changePhoto(for mode: ImagePickerMode){
imagePickerMode = mode
present(profileImagePicker, animated: true, completion: nil)
}

If you are using addTarget method for the buttons instead of IBAction, you may choose to assign a tag value to the button to separate them.

This also requires you to update ImagePickerMode to include rawValues which corresponds to button tags. Default rawValue for integers start from 0 with increment of 1. You should update both ImagePickerMode and changePhoto as following:

private enum ImagePickerMode: Int {
case coverPhoto
case profilePhoto
case unknown
}

private func changePhoto(for sender: UIButton) {
imagePickerMode = ImagePickerMode(rawValue: sender.tag) ?? .unknown
present(profileImagePicker, animated: true, completion: nil)
}

Eventually, delegate method becomes:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

guard let image = info[.editedImage] as? UIImage else { return }

switch imagePickerMode {
// handle cases and assign related image here!
}
}

Swift - Display two separate images in 2 UIImageViews in 1 ViewController

this isn't going to be complete, but will have the key parts you will need

class ResponsePhotoController: UIViewController, UIImagePickerControllerDelegate
{
var imageType : Int = 0 // use this to track the image type
// 0 for profile
// 1 for cover

in your code to go get the profile image

imageType = 0

and then when you go get the cover image

imageType = 1

and then in the imagePickerController

if imageType == 0
{
// set up the profile picture
}
else
{
// set up the cover image
}

I want to display two images at the same ViewController using 2 buttons

You can create a variable called focus that points to the UIImageView you're about to change. When the user has picked an image, just update the image of the focus.

class GetImagesViewController: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate {

var focus: UIImageView!

@IBAction func selectSignature1(_ sender: Any) {
focus = imageView1
openPhotoLibraryForSelectSignature()

}
@IBAction func selectPhoto(_sender: Any){
focus = imageView2
openPhotoLibraryForSelectPhoto()
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let image = info [UIImagePickerController.InfoKey.originalImage] as? UIImage

self.dismiss(animated: true, completion: nil)
focus.image = image
}

// rest of your code
}

Multiple Image Pickers in one Controller

The delegate function imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) also returns the UIImagePickerController that finished picking an image.

So you can use an if statement to check if the picker that finished is pickerOne or pickerTwo. Then you implement different behaviour according to the result of that.

Maybe set the pickers to nil after they have finished to clean up some memory.

class multiPickerVC : UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {


var pickerOne : UIImagePickerController?
var pickerTwo : UIImagePickerController?


override func viewDidLoad() {
//
}


@IBAction func getBackground(sender: AnyObject) {
pickerTwo = UIImagePickerController()
pickerTwo!.delegate = self
pickerTwo!.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
pickerTwo!.allowsEditing = true
self.presentViewController(pickerTwo!, animated: true, completion: nil)
}

@IBAction func selectAvatar(sender: AnyObject) {
pickerOne = UIImagePickerController()
pickerOne!.delegate = self
pickerOne!.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
pickerOne!.allowsEditing = true
self.presentViewController(pickerOne!, animated: true, completion: nil)
}


func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {

if picker == pickerOne {

// set image for button
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
self.addAvatar.setImage(image, forState: .Normal)

} else if picker == pickerTwo {

// set image for button
let image = info[UIImagePickerControllerOriginalImage] as? UIImage

self.headerImage.image = image
}

self.dismissViewControllerAnimated(true, completion: nil)

}
}


Related Topics



Leave a reply



Submit