I am trying to write a simple app that will update the ImageView with a photo from my photos library. I can open the photos library and select a photo, but after I do that the default image in the ImageViewer does not show up. Any idea why?
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBOutlet weak var photoView: UIImageView!
#IBAction func testGesture(_ sender: UITapGestureRecognizer) {
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerController.InfoKey.originalImage.rawValue] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
photoView.image = selectedImage
dismiss(animated: true, completion: nil)
}
}
You're not using the UIImagePickerControllerDelegate's didFinishPickingMediaWithInfo method. Remove the private and modify the didFinishPickingMediaWithInfo method to the UIImagePickerControllerDelegate method syntax and you're good to go.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
photoView.image = selectedImage
print(selectedImage)
dismiss(animated: true, completion: nil)
}
I'm using Apple's Swift iOS Tutorial. Which is throwing an error,
Cannot subscript a value of type '[String : Any]' with an index of type 'UIImagePickerController.InfoKey'
The function they defined is below.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// The info dictionary may contain multiple representations of the image. You want to use the original.
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
// Set photoImageView to display the selected image.
photoImageView.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
I'm using Xcode Version 10.0 beta 3, which includes Swift 4.2.
I'd like to understand how to traverse the docs to understand what might have changed or broken.
The signature of the method has changed in Swift 4.2
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
and you have to write
guard let selectedImage = info[.originalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
You can figure out such terminology changes yourself by reading the documentation or by commenting out the entire method, retype the first few characters and use code completion.
I'm following also the same tutorial, the updated code looks like this:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// The info dictionary may contain multiple representations of the image. You want to use the original.
guard let selectedImage = info[.originalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
// Set photoImageView to display the selected image.
photoImageView.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
Swift 5
In latest version of swift 4 or 5 the delegate method is given below, it should work
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// Code here
}
And use,
guard let selectedImage = info[.editedImage] as? UIImage else {
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let selectedImage = info[.editedImage] as? UIImage else {
}
}
Use like this,
guard let selectedImage = info[UIImagePickerController.InfoKey.originalImage.rawValue] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
In Swift 4 and 5 like so:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let selectedImage = info[.editedImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
self.myImageView.image = selectedImage
picker.dismiss(animated: true, completion: nil)
}
I am also following the tutorial. It is working after changing as below.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
// The info dictionary may contain multiple representations of the image. You want to use the original.
guard let selectedImage = info[.originalImage] as? UIImage
else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
// Set photoImageView to display the selected image.
photoImageView.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
I am using XCode 11 and Swift 5.
Method has been changed a little bit in Swift 4.2.
First initialise these two variables:
var imagePicker = UIImagePickerController()
var pickedImageProduct = UIImage()
extension yourViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate{
//create an IBAction to access Camera
#IBAction func accessCameraBtn(_ sender: UIButton) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.camera
self.present(imagePicker, animated: true, completion: nil)
}
//create an IBAction to access Gallery
#IBAction func accessGalleryBtn(_ sender: UIButton) {
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
self.present(imagePicker, animated: true, completion: nil)
}
//Final step put this Delegate
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let selectedImage = info[.originalImage] as? UIImage else {
Print("Error: \(info)")
}
pickedImageProduct = selectedImage
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
}
In Swift 4.2 you can write the function as:
func photoLib()
{
//opens Photo Library, call the function in a #IBAction func
let myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType =
UIImagePickerController.SourceType.photoLibrary
myPickerController.allowsEditing = true
present(myPickerController, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true)
guard let image = info[.editedImage] as? UIImage else {
print("No image found")
photoLabel.text = "Photo Not Found"
return
}
}
How do I use the updated UIImagePickerControllerDelegate API since it changed to [UIIMagePickerController.InfoKey : Any]? This part has been updated. I also searched here and I could not find an answer.
import UIKit
class adicionarNovoItemVc: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var textFieldNome: UITextField!
let imagePicker = UIImagePickerController()
#IBOutlet weak var namePreview: UILabel!
#IBOutlet weak var imagePreview: UIImageView!
let picker = UIImagePickerController()
#IBAction func botaoAdcFoto(_ sender: UIButton) {
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
???
}
}
Update:
After updating the didFinishPickingMediaWithInfo delegate to :
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[.originalImage] as! UIImage? {
self.imagePreview.image = image
self.picker.dismiss(animated: true, completion: nil)
}
}
I now get:
Cannot downcast from 'Slice>' to a more optional type 'UIImage?'
It's not really much different. In iOS 12, lots of the old constants names have been refactored.
Instead of the old key UIImagePickerControllerOriginalImage you now use UIImagePickerController.InfoKey.originalImage:
Something like:
let image = info[UIImagePickerControllerOriginalImage]
now becomes:
let image = info[.originalImage]
See the related documentation for UIImagePickerController.InfoKey.
Update:
You made several mistakes in your attempted didFinishPickingMediaWithInfo. You need:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage {
self.imagePreview.image = image
}
self.picker.dismiss(animated: true, completion: nil)
}
You need to set the mediaTypes of the picker using the availableMediaTypes class func of UIImagePickerController and retrieve the actual image from the info parameter.
#IBAction func botaoAdcFoto(_ sender: UIButton) {
picker.allowsEditing = true
picker.delegate = self
picker.sourceType = .photoLibrary
if let mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary) {
picker.mediaTypes = mediaTypes
}
present(picker, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as! UIImage? {
self. imagePreview.setImage(image, for: .normal)
self.picker.dismiss(animated: true, completion: nil)
}
}
I am attempting to learn more about the delegate pattern. I have written an app that accesses the user's camera roll and I want to display that image on the view controller after the user selects the image. Here is what I have thus far:
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var imagePickerView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
// Delegate Methods
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imagePickerView.image = image
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func pickAnImage(_ sender: Any) {
let pickerController = UIImagePickerController()
present(pickerController, animated: true, completion: nil)
}
}
The camera roll appears as expected and the Cancel buttons dismiss the modal. Selecting an image also dismisses the modal, however that image is not displayed on the screen. I have confirmed that my imagePickerController is corrected referenced as an outlet. What am I missing?
You have to dismiss the controller once the image is selected, maybe the following detailed function will help you.
For Swift 4.2:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var selectedImageFromPicker: UIImage?
if let editedImage = info[.editedImage] as? UIImage {
selectedImageFromPicker = editedImage
} else if let originalImage = info[.originalImage] as? UIImage {
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
imageView.image = selectedImage
}
dismiss(animated: true, completion: nil)
}
Before Swift 4.2:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var selectedImageFromPicker: UIImage?
if let editedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
selectedImageFromPicker = editedImage
} else if let originalImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
selectedImageFromPicker = originalImage
}
if let selectedImage = selectedImageFromPicker {
imageView.image = selectedImage
}
dismiss(animated: true, completion: nil)
}
Since I've received many points from this answer I'm adding a more concise answer (Just one line is required for setting the image to imageView).
Bonus Answer:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
imageView.image = (info[.editedImage] ?? info[.originalImage]) as? UIImage
dismiss(animated: true)
}
You need to set the view controller as the delegate of pickerController
// pickerController.delegate = self
Also check the imagePickerView outlet is connected.
Ensure you have made all inclusions in the info.plist file
Ensure you have all the delegates set
Ensure what you are using to display image (e.g if editing is set to true, then UIImagePickerControllerEditedImage else UIImagePickerControllerOriginalImage)
While choosing an image from the image picker in iOS 10 Swift 3 I am getting an error - Creating an image format with an unknown type is an error
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
imagePost.image = image
self.dismiss(animated: true, completion: nil)
}
The image is not getting selected and updated. I need help or suggestion to know if the syntax or anything regarding this method has been changed in iOS10 or Swift 3 or is there any other way to do this.
Below mentioned code did solve the problem for me -
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imagePost.image = image
} else{
print("Something went wrong")
}
self.dismiss(animated: true, completion: nil)
}
Remember to add delegate to self
let picker = UIImagePickerController()
picker.delegate = self // delegate added
Below code did solve the problem:
If user perform changes to selected image pull only that image otherwise pull original image source without any changes and finally dismiss image picker view controller.
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]){
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
imageView.image = image
}
else if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.image = image
} else{
print("Something went wrong")
}
self.dismiss(animated: true, completion: nil)
}
If you allow editing of the picture imageController.allowsEditing = true then you will need to get the edited image first:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
picker.dismissViewControllerAnimated(true, completion: nil)
if let image = info[UIImagePickerControllerEditedImage] as? UIImage {
imagePost.image = image
} else if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imagePost.image = image
} else {
imagePost.image = nil
}
}
The accepted solution by Jeetendra Choudhary works.Although in Xcode 8 with Swift 3 , I noticed that it generates a warning :
Instance method 'imagePickerController(_:didFinishPickingMediaWithInfo:)' nearly matches optional requirement 'imagePickerController(_:didFinishPickingMediaWithInfo:)' of protocol 'UIImagePickerControllerDelegate'
and suggests to add either #nonobjc or private keyword to silence the warning.If you silence the warning using these suggestions , the solution no longer works though.
I found the default images in the photo library could couse this problem.
If you drag an image from your computor onto the simulator and choose it.
this problem is solved
According Abdurohman's answer, i change my code and solve the problem,thanks.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
photoImageView.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
Add this to viewDidload()
imagepicker.delegate = self
Add "_" in function parameters.
from
func imagePickerController(picker: UIImagePickerController ...
to
func imagePickerController(_ picker: UIImagePickerController ...
This worked for me:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.image = image
self.dismiss(animated: true, completion: nil)
}
}
If this helps anyone, I had this happen when I subclassed UIImageView to create a rounded view. It also happened when I added the below line in viewDidLoad()
imageView.layer.cornerRadius = self.imageView.frame.size.width / 2
I ended up adding the line in viewWillLayoutSubViews and it worked. See this for more details:
clipsToBounds causes UIImage to not display in iOS10 & XCode 8
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
self.dismiss(animated: true, completion: nil)
self.imageTook.image = image
}
Change didFinishPickingMediaWithInfo info: [String : AnyObject] ,
to didFinishPickingMediaWithInfo info: [String : Any]
For Xcode 8.1 with swift 3, After changing the delegate method as below
change your
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
imagePost.image = image
self.dismiss(animated: true, completion: nil)
}
function to
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
{
imagePost.image = info[UIImagePickerControllerOriginalImage] as? UIImage
picker.dismiss(animated: true, completion: nil)
}
I forgot to add UINavigationControllerDelegate along with UIImagePickerControllerDelegate in
class ViewController:UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate
You would have added an variable at the beginning like
var imagePicker = UIImagePickerController()
and setting delegate and call a function in viewdidload() as
imagePicker.delegate = self
viwImagePick()
Then explain that function as
//ImagePicker
func viwImagePick(){
let alert = UIAlertController(title: nil, message: "Choose your source", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Camera", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print("Camera selected")
self.openCamera()
//Code for Camera
//cameraf
})
alert.addAction(UIAlertAction(title: "Photo library", style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
print("Photo selected")
self.openGallary()
//Code for Photo library
//photolibaryss
})
self.present(alert, animated: true, completion: nil)
}
func openCamera()
{
imagePicker.sourceType = UIImagePickerControllerSourceType.camera
if UIDevice.current.userInterfaceIdiom == .phone
{
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let popover = UIPopoverController(contentViewController: imagePicker)
popover.present(from: profileImgViw.frame, in: self.view, permittedArrowDirections: UIPopoverArrowDirection.any, animated: true)
}
}
func openGallary()
{
imagePicker.sourceType = UIImagePickerControllerSourceType.savedPhotosAlbum
if UIDevice.current.userInterfaceIdiom == .phone
{
self.present(imagePicker, animated: true, completion: nil)
}
else
{
let popover = UIPopoverController(contentViewController: imagePicker)
popover.present(from: profileImgViw.frame, in: self.view, permittedArrowDirections: UIPopoverArrowDirection.any, animated: true)
}
}
Now the image is added to image view from the library
I think you are missing a connection between photoImageView and the image.
Take a look my screenshots below:
I think you are missing a connection between photoImageView and the image.
Take a look my screenshots below:
Good luck!
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
imgViewPhoto.image = image
} else{
print("Something went wrong")
}
picker.dismiss(animated: true, completion: nil)
}
Be sure to also include theUINavigationControllerDelegate delegate. This solved the issue for me.
try below
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
print("image selected");
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImag
self.dismiss(animated: true, completion: nil)
UIImg.image = selectedImage
}
This worked for me.
Just copy and paste it exactly.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// The info dictionary contains multiple representations of the image, and this uses the original.
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
// Set photoImageView to display the selected image.
photoImageView.image = selectedImage
// Dismiss the picker.
dismiss(animated: true, completion: nil)
}
What I did was that once I got the image from didFinishPickingMediaWithInfo, I called:
func prepareImageForSaving(image:UIImage) {
// create NSData from UIImage
guard let imageData = UIImageJPEGRepresentation(image, 1) else {
// handle failed conversion
print("jpg error")
return
}
self.saveImage(imageData: imageData as NSData)
}
func saveImage(imageData: NSData) {
imageDatas = imageData
}
to save it in NSData format.
The console still warned me on "[Generic] Creating an image format with an unknown type is an error" but at least my imageView gets updated to the selected image rather than showing the previous one from viewDidLoad.
// image picker with collection view
class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet var img: UIImageView!
#IBOutlet weak var collview: UICollectionView!
var image = NSMutableArray()
let imgpkr = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
imgpkr.delegate = self
}
#IBAction func btnselect(_ sender: UIButton) {
imgpkr.allowsEditing = true // false
imgpkr.sourceType = .photoLibrary
imgpkr.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
present(imgpkr, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let choose = info[UIImagePickerControllerOriginalImage]as!UIImage
let edit = info[UIImagePickerControllerEditedImage]as!UIImage
img.contentMode = .scaleAspectFit
img.image = edit
//MARK:- Add image in collview
image.add(edit)
collview.reloadData()
dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
//MARK:- Collection View
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return image.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collview.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)as! CollectionViewCell1
cell.img1.image = image.object(at: indexPath.item)as! UIImage
return cell
}
For me I was getting the error:
"fatal error: unexpectedly found nil..."
when you select imagein imagepicker.
To get around the problem, I created the outlet for the imageView again.