Picking image from gallery in Swift - ios

I have a image view inside the view controller. I want to set this image when user selects an image from gallery.
I tried this code:
#IBOutlet var profilePicture: UIImageView!
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.dismissViewControllerAnimated(true, completion:nil)
println("image selected from gallery")
self.profilePicture.image = image
}
It prints debug message to console but it is not changing the image. How can I fix this ?

You just forgot to assign image you got from gallery to your UIImageView.
#IBOutlet var profilePicture: UIImageView!
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
profilePicture.image = image
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
println("image selected from gallery")
self.profilePicture.image=image
}

Can you try this code:
#IBOutlet var profilePicture: UIImageView!
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
println("image selected from gallery")
dispatch_async(dispatch_get_main_queue()) {
self.profilePicture.image=image
}
}

#IBAction func chooseProfilePicBtnClicked(sender: AnyObject) {
let alert:UIAlertController=UIAlertController(title: "Choose Image", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
let cameraAction = UIAlertAction(title: "Camera", style: UIAlertActionStyle.Default)
{
UIAlertAction in
self.openCamera()
}
let gallaryAction = UIAlertAction(title: "Gallary", style: UIAlertActionStyle.Default)
{
UIAlertAction in
self.openGallary()
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel)
{
UIAlertAction in
}
// Add the actions
picker.delegate = self
alert.addAction(cameraAction)
alert.addAction(gallaryAction)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true, completion: nil)
}
func openCamera(){
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
picker.sourceType = UIImagePickerControllerSourceType.Camera
self .presentViewController(picker, animated: true, completion: nil)
}else{
let alert = UIAlertView()
alert.title = "Warning"
alert.message = "You don't have camera"
alert.addButtonWithTitle("OK")
alert.show()
}
}
func openGallary(){
picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(picker, animated: true, completion: nil)
}
//MARK:UIImagePickerControllerDelegate
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]){
picker .dismissViewControllerAnimated(true, completion: nil)
imageViewRef.image=info[UIImagePickerControllerOriginalImage] as? UIImage
}
func imagePickerControllerDidCancel(picker: UIImagePickerController){
print("picker cancel.")
}

To display a selected image using UIImagePickerController use the following code:
// Add these protocols into your class declaration
UIImagePickerControllerDelegate, UINavigationControllerDelegate
// Set the delegate
#IBAction func presentViewImagePicker(sender: AnyObject) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
presentViewController(imagePicker, animated: true, completion: nil)
}
// Use these two methods from UIImagePickerControllerDelegate
Check the documentation https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerControllerDelegate_Protocol/index.html
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageRetrieved.contentMode = .ScaleAspectFill
imageRetrieved.image = pickedImage
}
self.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
Hope it helps

The delegate method you are using is deprecated. You should replace it with this:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *, id> *)info
Use this link to learn which keys you need to use to retrieve the image from the dictionary.

Related

Swift 4 Image Picker Not Changing UIImageView

For some reason in my new project this code is not working which has worked for me before. The current code does not change the ui of profileImage.
Delegates
UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate
Code:
#IBOutlet weak var profileImage: UIImageView!
#IBAction func changeProfilePicture(_ sender: Any) {
print("Profile picture tapped")
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
let alertController = UIAlertController(title: "Add Picture", message: "", preferredStyle: .actionSheet)
let photoLibraryAction = UIAlertAction(title: "Photo Library", style: .default) { (action) in
pickerController.sourceType = .photoLibrary
self.present(pickerController, animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alertController.addAction(photoLibraryAction)
alertController.addAction(cancelAction)
present(alertController, animated: true, completion: nil)
}
#objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : Any]?) {
self.profileImage.image = image
self.dismiss(animated: true, completion: nil)
}
Console Output
errors encountered while discovering extensions: Error
Domain=PlugInKit Code=13 "query cancelled"
UserInfo={NSLocalizedDescription=query cancelled}
I have tried
#objc func
internal func
#objc internal func
self.profileImage.image = image does not set the UI and change the image
Correct delegate method
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.originalImage] as? UIImage {
self.profileImage.image = image
}
else
if let image = info[.editedImage] as? UIImage {
self.profileImage.image = image
}
self.dismiss(animated: true, completion: nil)
}

Circular crop in UIImagePickerController

How to add a circular cropper in UIImagePickerController when camera is running ? where picture should be cropped as per the circular area. (iPad)
class imagePickerHelper: NSObject {
override init() {}
var chosenImage: UIImage?
var getimage: ((_ selectedItem: UIImage ,_ selectedvalue: Bool) -> Void)?
static let helper = imagePickerHelper()
var viewcontroller = UIViewController()
func opencamera (withParentViewController ParentViewController: UIViewController,source: UIImagePickerControllerSourceType,selectedimage: #escaping (_ value: UIImage?,_ selectedvalue: Bool?) -> Void){
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let picker = UIImagePickerController()
viewcontroller = ParentViewController
picker.delegate = self
picker.sourceType = source
picker.allowsEditing = true
picker.sourceType = UIImagePickerControllerSourceType.camera
picker.cameraCaptureMode = .photo
picker.cameraDevice = UIImagePickerController.isCameraDeviceAvailable(.front) ? .front : .rear
picker.modalPresentationStyle = .fullScreen
viewcontroller.present(picker,animated: true,completion: nil)
getimage = selectedimage
}
else{
noCamera()
}
}
func noCamera() {
let alertVC = UIAlertController(
title: "No Camera",
message: "Sorry, this device has no camera",
preferredStyle: .alert)
let okAction = UIAlertAction(
title: "OK",
style: .default,
handler: nil)
alertVC.addAction(okAction)
viewcontroller.present(
alertVC,
animated: true,
completion: nil)
}
}
extension imagePickerHelper: UIImagePickerControllerDelegate,UINavigationControllerDelegate{
//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
chosenImage = info[UIImagePickerControllerEditedImage] as? UIImage //2
// myImageView.contentMode = .scaleAspectFit //3
// myImageView.image = chosenImage //4
getimage!(chosenImage!,true)
viewcontroller.dismiss(animated: true, completion: nil) //5
picker.dismiss(animated: true, completion: nil);
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
viewcontroller.dismiss(animated: true, completion: nil)
}
}

Cropping an image with imagepickercontroller in swift

I am currently making a program in swift that involves a screen of choosing an image from either camera or photo library using action sheet. This is fully functional however I would like to be able to choose a square section from the selected image, similar to apple default apps. How can I implement this? Here is my functional code:
func chooseImage(_ sender: Any) {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
let actionSheet = UIAlertController(title: "Photo Source", message: "Choose a source", preferredStyle: .actionSheet)
actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: { (action:UIAlertAction) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
imagePickerController.sourceType = .camera
self.present(imagePickerController, animated: true, completion: nil)
}else{
print("Camera not available")
}
}))
actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: { (action:UIAlertAction) in
imagePickerController.sourceType = .photoLibrary
self.present(imagePickerController, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Default", style: .default, handler: { (action:UIAlertAction) in
self.avatarImageView.image = UIImage(named: "Avatar.png")
}))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(actionSheet, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
avatarImageView.image = image
picker.dismiss(animated: true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
// Saves the User singleton object onto the device
static func saveData() {
let savedData = NSKeyedArchiver.archivedData(withRootObject: User.sharedUser)
UserDefaults.standard.set(savedData, forKey: "user")
}
You can use default controls to achieve image cropping.
self.imgPicker.allowsEditing = true
Delegate Method
//MARK: image picker delegate method
//MARK:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var image : UIImage!
if let img = info[UIImagePickerControllerEditedImage] as? UIImage
{
image = img
}
else if let img = info[UIImagePickerControllerOriginalImage] as? UIImage
{
image = img
}
picker.dismiss(animated: true,completion: nil)
}
Swift 4.0+
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
var image : UIImage!
if let img = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
{
image = img
}
else if let img = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
{
image = img
}
picker.dismiss(animated: true, completion: nil)
}
Don't forget to set allowsEditing to true.
Another option is to use TOCropViewController. Its does more with much less code. What I found good about it that it allows you to change the cropping rectangle.
class ViewController: UIViewController, CropViewControllerDelegate {
... //your viewcontroller code
func presentCropViewController {
let image: UIImage = ... //Load an image
let cropViewController = CropViewController(image: image)
cropViewController.delegate = self
present(cropViewController, animated: true, completion: nil)
}
func cropViewController(_ cropViewController: CropViewController,
didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {
// 'image' is the newly cropped version of the original image
}
}
Swift 5.0
The shortest way of declaring:
//MARK: image picker delegate method
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
var image : UIImage!
if let img = info[.editedImage] as? UIImage {
image = img
} else if let img = info[.originalImage] as? UIImage {
image = img
}
picker.dismiss(animated: true,completion: nil)
}
Button sender:
#objc func buttonClicked(sender: UIButton!) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerController.SourceType.photoLibrary
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
}
Don't forget to grant Photo Library access in .plist
- (void)cropViewController:(TOCropViewController *)cropViewController didCropToImage:(UIImage *)image withRect:(CGRect)cropRect angle:(NSInteger)angle
{
[[NSUserDefaults standardUserDefaults] setObject:UIImageJPEGRepresentation(image, 1) forKey:#"image"];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"cameraOn"];
[cropViewController dismissViewControllerAnimated:YES completion:^{
[self performSegueWithIdentifier:#"YourSegueIdentifier" sender:self];
}];
//UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
For (iOS13): Do all ViewController "cropController.modalPresentationStyle =.fullScreen" using storyboard or code.
This is work good and easily navigate to another controller. I also attached image so you can easily understand how to change presentation style.

Include UIImagePickerController in a view

I need to make a view that works like pages, with a popup in which I can choose to pick a photo from my library or create a new one.
Currently, I have a ViewController, present as Popover. In the ViewController, I inserted a ContainerView and I declared that its class is UIImageViewController. This is showing me the photo library but I don't find how to pick anything in : My ViewController presented as Popover.
When I choose a photo, nothing's happening. I've tried to put some functions
(func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!))
in my ViewController but it does not work. I've read that UIImagePickerController does not support subclassing, so how Pages do this stuff ?
Here is my ViewController code :
import UIKit
class MenuAddResources: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var newMedia: Bool?
let imagePicker = UIImagePickerController()
#IBAction func takePhoto(sender: AnyObject) {
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)){
//load the camera interface
let picker : UIImagePickerController = UIImagePickerController()
picker.sourceType = UIImagePickerControllerSourceType.Camera
picker.delegate = self
picker.allowsEditing = false
self.presentViewController(picker, animated: true, completion: nil)
self.newMedia = true
}
else{
//no camera available
let alert = UIAlertController(title: NSLocalizedString("ERROR", comment: ""), message: NSLocalizedString("NO_CAMERA", comment: ""), preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Default, handler: {(alertAction)in
alert.dismissViewControllerAnimated(true, completion: nil)
}))
self.presentViewController(alert, animated: true, completion: nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func image(image: UIImage, didFinishSavingWithError error: NSErrorPointer, contextInfo:UnsafePointer<Void>) {
if error != nil {
let alert = UIAlertController(title: NSLocalizedString("ERROR", comment: ""), message: NSLocalizedString("IMAGE_SAVE_FAILED", comment: ""), preferredStyle: UIAlertControllerStyle.Alert)
let cancelAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .Cancel, handler: nil)
alert.addAction(cancelAction)
self.presentViewController(alert, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!){
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
// Let's store the image
let now:Int = Int(NSDate().timeIntervalSince1970)
let imageData = UIImageJPEGRepresentation(image, 85)
//imageData?.writeToFile(documentsDirectory + "/\(now).jpg", atomically: true)
print(imageData)
/* will do stuff with the image */
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
}
It appears you are using UIImagePickerViewController through a
container view and therefore the delegate isnt set , thus no callbacks
to receiving the image picked methods.
To fix this, you must override prepareForSegue in your class
and in that cast the segue.destinationViewController to your picker and set its delegate to self

UIImagePickerControllerDelegate functions are not being called

I have a class where I am calling the UIImagePickerController to select an image and return it so I can use it somewhere else in my code.
Now I set the delegate and implement the necessary function I need, but the delegate functions aren't being called.
The portion of my code that has the issue:
import UIKit
typealias PhotoTakingHelperCallback = (UIImage? -> Void)
class PhotoTakingHelper: NSObject
{
weak var viewController:UIViewController!
var callback: PhotoTakingHelperCallback
var imagePickerController: UIImagePickerController?
init(viewController:UIViewController , callback:PhotoTakingHelperCallback) {
self.viewController = viewController
self.callback = callback
super.init()
showPhotoSourceSelection()
}
func showPhotoSourceSelection() {
let alertController = UIAlertController(title: nil, message: "Where do you want to get your picture from?", preferredStyle: .ActionSheet)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alertController.addAction(cancelAction)
let photoLibraryAction = UIAlertAction(title: "Photo from Library", style: .Default) { (action) -> Void in
self.showImagePickerController(.PhotoLibrary)
}
alertController.addAction(photoLibraryAction)
if (UIImagePickerController.isCameraDeviceAvailable(.Rear) ) {
let cameraAction = UIAlertAction(title: "Photo from Camera", style: .Default, handler: { (action) -> Void in
self.showImagePickerController(.Camera)
})
alertController.addAction(cameraAction)
}
viewController.presentViewController(alertController, animated: true, completion: nil)
}
func showImagePickerController(sourceType: UIImagePickerControllerSourceType) {
imagePickerController = UIImagePickerController()
imagePickerController!.delegate = self
imagePickerController!.sourceType = sourceType
print("Set the delegate \(imagePickerController?.delegate?.isMemberOfClass(PhotoTakingHelper))")
self.viewController.presentViewController(imagePickerController!, animated: true, completion: nil)
}
}
extension PhotoTakingHelper: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
print("HELLO?")
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
viewController.dismissViewControllerAnimated(false, completion: nil)
print("calling the callback now " )
callback(image)
print("Finished calling the callback")
}
}
I've checked iPhone: UIImagePickerControllerDelegate methods not Invoked? and a similar problem and many more but none have solved the issue.
I've realized that none of the delegate methods are invoked as when I run through the program on the simulator and choose an image in the photo library, the console only prints.
Set the delegate Optional(true)
You're creating a PhotoTakingHelper but you're not keeping a reference to it. That is, you're doing something like this:
// In your view controller
#IBAction func pickImageButtonWasTapped() {
_ = PhotoTakingHelper(viewController: self) { image in
print("Callback!")
}
}
The UIImagePickerController keeps only a weak reference to its delegate, which is not enough to keep it alive, so you have to keep a strong reference to it. You could do it by storing the helper in an instance variable of your view controller, like this:
// In your view controller
var helper: PhotoTakingHelper?
#IBAction func pickImageButtonWasTapped() {
helper = PhotoTakingHelper(viewController: self) { image in
print("Callback!")
}
}
Or you could make the helper keep a reference to itself, like this:
// In PhotoTakingHelper
var me: PhotoTakingHelper?
init(viewController:UIViewController , callback:PhotoTakingHelperCallback) {
self.viewController = viewController
self.callback = callback
super.init()
me = self
showPhotoSourceSelection()
}
And then you need to set the reference to nil when the image picker is done, to let the helper be deallocated:
extension PhotoTakingHelper: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
viewController.dismissViewControllerAnimated(false, completion: nil)
callback(info[UIImagePickerControllerOriginalImage] as? UIImage)
me = nil
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
viewController.dismissViewControllerAnimated(false, completion: nil)
me = nil
}
}

Resources