From this article, I'm learning to take picture / choose from library, and put the result in a UIImageView.
#IBOutlet var theImage: UIImageView!;
#IBAction func openLibrary (sender: UIButton) {
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
imagePicker.allowsEditing = true
self.presentViewController(imagePicker, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
theImage.image = image;
self.dismissViewControllerAnimated(true, completion: nil);
}
The result is like this:
Before click on the select from library
While selecting the image
Image picker result
The image like cropped, even though I have set the mode to be Aspect Fit. What's wrong?
EDIT:
Scale to fit? This is all I have on the image mode:
Related
I use gestureRecognizer with UIImageView. And I have two UIImageView. Me need upload image in both UIImageView. For opening UIImagePickerController() I use gestureRecognizer on both UIImageView.
So me need upload image in different UIImageView in func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
How I can upload image from library?
It's my code:
#IBOutlet weak var mainPhotoImageView: UIImageView!
#IBOutlet weak var addImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
configureGestureRecognizer()
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerEditedImage] as? UIImage
if chosenImage != nil {
logoImageView.image = chosenImage
dismiss(animated: true, completion: nil)
}
}
#objc func addLogoHall(_ sender: AnyObject) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
}
#objc func addMainPhoto(_ sender: AnyObject) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
}
func configureGestureRecognizer() {
let addHallLogo = UITapGestureRecognizer(target: self, action: #selector(AddPhotoAndLogoViewController.addLogoHall(_:)))
logoImageView.isUserInteractionEnabled = true
logoImageView.addGestureRecognizer(addHallLogo)
let addMainPhotoImage = UITapGestureRecognizer(target: self, action: #selector(AddPhotoAndLogoViewController.addMainPhoto(_:)))
mainPhotoImageView.isUserInteractionEnabled = true
mainPhotoImageView.addGestureRecognizer(addMainPhotoImage)
}
So in func imagePickerController me need detect which gestureRecognizer was used. Or maybe have alternative opportunity to do it?
You can add diffrent tag for pickers like this way:
#objc func addLogoHall(_ sender: AnyObject) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.sourceType = .photoLibrary
picker.view.tag = 1
present(picker, animated: true, completion: nil)
}
#objc func addMainPhoto(_ sender: AnyObject) {
let picker = UIImagePickerController()
picker.delegate = self
picker.allowsEditing = true
picker.view.tag = 2
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
}
And then you can identify by this tag like this way:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerEditedImage] as? UIImage
if chosenImage != nil {
if(picker.view.tag == 1) {
logoImageView.image = chosenImage
} else {
mainImageView.image = chosenImage
}
dismiss(animated: true, completion: nil)
}
}
While Jogendar's answer is good, I see one pitfall. The if-else will grow as the number of image view instances increase in your view controller file. This might get messy and unnecessarily large quickly. Might I suggest an alternative solution:
class ImageSelectionController: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
weak var delegate: ImageSelectionControllerDelegate?
private weak var imageView: UIImageView?
private weak var presentingViewController: UIViewController?
// MARK: - Initialization
init(withImageView imageView: UIImageView?, andPresentingViewController viewController: UIViewController?) {
self.imageView = imageView
self.presentingViewController = viewController
}
// MARK: - Public
func presentImagePickerController(withConfigurationHandler handler: ((UIImagePickerController) -> Void)? = nil) -> Void {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.sourceType = .photoLibrary
handler?(picker)
picker.delegate = self
}
// MARK: - UIImagePickerController
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let chosenImage = info[UIImagePickerControllerEditedImage] as? UIImage
self.imageView?.image = chosenImage
self.delegate?.controller(self, didFinishPickingImage: chosenImage, forImageView: self.imageView)
picker.dismiss(animated: true, completion: nil)
}
}
protocol ImageSelectionControllerDelegate: AnyObject {
func controller(_ controller: ImageSelectionController, didFinishPickingImage image: UIImage?, forImageView: UIImageView?) -> Void
}
// ---- Your View Controller ---- //
#IBOutlet weak var logoImageView: UIImageView?
#IBOutlet weak var mainPhotoImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
configureGestureRecognizer()
}
#objc func addLogoHall(_ sender: AnyObject) {
let controller = ImageSelectionController.init(withImageView: self.logoImageView, andPresentingViewController: self)
controller.delegate = self
controller.presentImagePickerController()
}
#objc func addMainPhoto(_ sender: AnyObject) {
let controller = ImageSelectionController.init(withImageView: self.logoImageView, andPresentingViewController: self)
controller.presentImagePickerController { (picker) in
picker.sourceType = .camera
}
}
// MARK: - ImageSelectionControllerDelegate
func controller(_ controller: ImageSelectionController, didFinishPickingImage image: UIImage?, forImageView: UIImageView?) {
print("image picked!")
}
Doing it this way, you could put all the UIImagePickerController related code in one place and you wouldn't need to have any if-else cases. Again, there is no right or wrong answer and someone might also find some other flaw in my solution. Its just a matter of how you want to structure your code.
Happy coding!
class MyPage: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var imagePicker = UIImagePickerController()
#IBOutlet weak var selectImage: UIButton!
override func viewDidLoad() {
imagePicker.sourceType = .photoLibrary
imagePicker.delegate = self
}
#IBAction func selectImage(_ sender: Any) {
print("a")
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){
print("b")
imagePicker.allowsEditing = false
imagePicker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
self.present(imagePicker, animated: true,completion: nil)
}
#objc func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!){
self.dismiss(animated: true, completion: { () -> Void in
print("dismiss")
})
print(image)
selectImage.setImage(image, for: .normal)
}
}
If touch button print a and b and pop photoLibrary
but select Photo not call imagePickerController
do nothing after select photo
how to use imagepicker in swift 4?
Remove #objc from Delegate method and delegate method is this so replace your function with this :
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any])
and get image by using this :
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {return}
import UIKit
class ViewController: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let imageView = UIImageView()
let imagepicker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
self.imagepicker.delegate = self
imageView.frame = CGRect(x: 40, y: 150, width: 100, height: 100)
self.view.addSubview(imageView)
}
#IBAction func uploadImage(_ sender : UIButton) {
imagepicker.cameraDevice = .rear
imagepicker.cameraCaptureMode = .photo
imagepicker.sourceType = .photoLibrary
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else {
return
}
imageView.image = image
print(image)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.dismiss(animated: true, completion: nil)
}
}
I'm using Swift, and I called once the album, with a systematic approach, and then allowed to dismiss the normal way (perhaps even less the other way), but after a call to complete systems approach, memory will rise 20M, I wrote a simple example, found that still the case, I wrote immediate window in appdelegate. Swift rootViewController switch inside, still can not eliminate this 20M memory. Because I called up a photo album directly 20M, but many times I'll call the album now, not in this demo, so I need to solve this 20M problem.
The code:
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
var bu = UIButton()
bu.frame = CGRectMake(80, 80, 80, 80)
bu.backgroundColor = UIColor.redColor()
bu.addTarget(self, action: "hh", forControlEvents: .TouchUpInside)
self.view.addSubview(bu)
}
func hh() {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.allowsEditing = true
imagePicker.sourceType = .PhotoLibrary
presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
picker.dismissViewControllerAnimated(true, completion: nil)
var tt = TViewController()
self.presentViewController(tt, animated: true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController){
picker.dismissViewControllerAnimated(true, completion: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Since iOS 9 and Xcode 7 I am no longer able to implemet a UIImagePickerController on an iPad (both device and simulator). The code below works on the iPad but only prior to iOS 9. When using iOS 9+ the presented image (after the UIImagePickerController is dismissed) is an incorrect version of the selected image. Without re-sizing or cropping the final image is only the top right corner of the original image ?? Plus another problem - If imagePicker.allowsEditing = false, you are unable to select images from the PhotoLibrary ??
#IBAction func photoButton(sender: AnyObject) {
imagePicker.allowsEditing = true
imagePicker.sourceType = .PhotoLibrary
self.presentViewController(imagePicker, animated: false, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerEditedImage] as? UIImage {
self.imageView.image = pickedImage
dismissViewControllerAnimated(true, completion: { () -> Void in
})
}
Heres an example of a selected image presented in a UIImagePickerController. (notice how the selected image is presented very small and not full size/width of screen as before)
After selecting the use button within the UIImagePickerController the final image is only the top right of the original image. What am I doing wrong or is UIImagePickerController broken on iOS 9 ?
This is a bug from Apple:
http://openradar.appspot.com/radar?id=5032957332946944
Current lousy workaround:
if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
imagePicker.allowsEditing = false
} else {
imagePicker.allowsEditing = true
}
Swift 3.0:
if UIDevice.current.userInterfaceIdiom == .pad {
}
Refer the below coding
#IBAction func photoButton(sender: AnyObject)
{
if(UIImagePickerController .isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera))
{
picker!.sourceType = UIImagePickerControllerSourceType.Camera
self .presentViewController(picker!, animated: true, completion: nil)
}
else
{
let alertWarning = UIAlertView(title:"Warning", message: "You don't have camera", delegate:nil, cancelButtonTitle:"OK", otherButtonTitles:"")
alertWarning.show()
}
}
func openGallary()
{
picker!.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(picker!, animated: true, completion: nil)
}
//PickerView Delegate Methods
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
{
picker .dismissViewControllerAnimated(true, completion: nil)
imageView.image=info[UIImagePickerControllerOriginalImage] as? UIImage
}
func imagePickerControllerDidCancel(picker: UIImagePickerController)
{
println("picker cancel.")
}
You need to make sure you have the correct frame for your imageview and the contentmode for your imageview should be aspectfit and the image returned by the picker is of type [UIImagePickerControllerOriginalImage]
[imageView setFrame:imageViewRect];
[imageView setContentMode:UIViewContentModeScaleAspectFit];
Swift:
imageView.setFrame(imageViewRect)
imageView.setContentMode(UIViewContentModeScaleAspectFit)
and coming to the allowsEditing property, It is not related to photo selection.
It is a Boolean value indicating whether the user is allowed to edit a
selected still image or movie.
If you want to select photos from camera library, then you need to modify the source type to
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
Update:
LEts say you have selected one image and display it on the image view. I assume you have one imageview on the view, and the imageview frame is equal to the view frame. If the IB is of freeform , I assume the size 600x600 for the imageview frame in the IB.
if you simply do:
_startImageView.image=_img;
The result will be:
Now let's make some changes to the image to be displayed in the imageview:
CGRect scaledRect = AVMakeRectWithAspectRatioInsideRect(_img.size, CGRectMake(0, 0, self.startImageView.frame.size.width, self.startImageView.frame.size.height));
UIGraphicsBeginImageContext(CGSizeMake(_startImageView.frame.size.width,_startImageView.frame.size.height));
[_img drawInRect:scaledRect];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
_startImageView.image=scaledImage;
and now the image will be:
The original image choosen is of size 640x426, when not scaled.
The original image choosen is of size 1536x1286 when scaled to max(with two finger zoom action).
As you can see, still there is no huge change in the image, it is because the image is already cropped/scaled by the time your imageview recieved the image!!!
So even though you try to do:
[_img drawInRect:_startImageView.frame];
The image will not be drawn as per our need, as the image is already scaled right at them moment as the image given by the picker is the edited image.
Solution:
To fix this, you need to select the original image from picker in didFinishPickingMediaWithInfo: method
info[UIImagePickerControllerOriginalImage];
which gives you the image:
This code is relatively similar to #pkc456, just a little shorter.
This works perfectly for me:
import UIKit
class PostImageViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
#IBOutlet var imageToPost: UIImageView!
#IBAction func chooseImage(sender: AnyObject) {
var image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
image.allowsEditing = false //or true additional setup required.
self.presentViewController(image, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.dismissViewControllerAnimated(true, completion:nil)
}
Does this work?
I am working on xcode 7.1(Swift) and found your code appropriate. I also wrote the below code on my project and it is working successfully.
func showPicker(){
let type = UIImagePickerControllerSourceType.PhotoLibrary
if(UIImagePickerController.isSourceTypeAvailable(type)){
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
pickerController.allowsEditing = false
self.presentViewController(pickerController, animated: true, completion: nil)
}
}
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
let imageView = self.view.viewWithTag(20) as! UIImageView
let selectedImage : UIImage = image
imageView.image=selectedImage
self.dismissViewControllerAnimated(true, completion: nil)
}
The only difference in your code and my code is about visibility of ImagePickerController instance. For your reference, I upload my code at:-
https://www.dropbox.com/s/pe0yikxsab8u848/ImagePicker-Swift.zip?dl=0
My idea is just look at my code once, may be you will get an idea about which section of your code malfunctioning.
It seems like you are using IB and auto layout but have set a right constraint. Try to add some constraint in your storyboard.
for me I was solved, showing mode as popover
#IBAction func photoButton(sender: AnyObject) {
imagePicker.allowsEditing = true
imagePicker.sourceType = .PhotoLibrary
let controller = self.imagePicker
controller.modalPresentationStyle = UIModalPresentationStyle.Popover
controller.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
let popover = controller.popoverPresentationController
popover?.sourceView = self
controller.preferredContentSize = CGSize(
width: self.frame.width * 0.6,
height: self.frame.height * 0.6
)
popover?.sourceRect = CGRectMake(
CGRectGetMidX(self.bounds),
CGRectGetMidY(self.bounds),
0,
0
)
self.presentViewController(self.imagePicker, animated: true, completion: nil)
}
I want the view to load with a default image and let the user tap this image to select another from the photo library. I'm doing this way, but the tap gesture is not working, what am I doing wrong?
class ProfileViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let imagePicker = UIImagePickerController()
#IBOutlet var profilePicture: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: Selector("selectProfilePicture"))
profilePicture.addGestureRecognizer(tap)
imagePicker.delegate = self
}
func selectProfilePicture() {
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
self.dismissViewControllerAnimated(true, completion: nil)
profilePicture.image = image
}
}
Try to enable userInteractionEnabled on your UIImageView:
profilePicture.userInteractionEnabled = true
I tend to just put an invisible UIButton on top of the image. Easiest / simplest way to do it, without overcomplicating it.