I have two outlets for two different UIImageViews, when I select the first one it'll appear on the first Image View but when I select the second Image, it replaces the first Image View even though it's connected to the second ImageView. This is my code for the Select Image button.
#IBOutlet weak var myImageView1: UIImageView!
#IBOutlet weak var myImageView2: UIImageView!
#IBAction func pickImage1(_ sender: Any) {
let image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.photoLibrary
image.allowsEditing = false
self.present(image, animated: true)
}
//Add didFinishPickingMediaWithInfo here
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
myImageView1.image = image
}
else {
//error
}
self.dismiss(animated: true, completion: nil)
}
#IBAction func pickImage2(_ sender: Any) {
let image2 = UIImagePickerController()
image2.delegate = self
image2.sourceType = UIImagePickerControllerSourceType.photoLibrary
image2.allowsEditing = false
self.present(image2, animated: true)
}
//Add didFinishPickingMediaWithInfo here
func imagePickerController2(_ picker2: UIImagePickerController, didFinishPickingMediaWithInfo2 info2: [String : Any]) {
if let image2 = info2[UIImagePickerControllerOriginalImage] as? UIImage {
myImageView2.image = image2
}
else {
//error
}
self.dismiss(animated: true, completion: nil)
}
Try this code. So you need a flag to remember which image view is clicked, and then set image base on that.
var selected = 1
#IBAction func pickImage1(_ sender: Any) {
let image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.photoLibrary
image.allowsEditing = false
selected = 1
self.present(image, animated: true)
}
//Add didFinishPickingMediaWithInfo here
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
if selected == 1 {
myImageView1.image = image
} else {
myImageView2.image = image
}
}
else {
//error
}
self.dismiss(animated: true, completion: nil)
}
#IBAction func pickImage2(_ sender: Any) {
let image2 = UIImagePickerController()
image2.delegate = self
image2.sourceType = UIImagePickerControllerSourceType.photoLibrary
image2.allowsEditing = false
selected = 2
self.present(image2, animated: true)
}
Moving forward, when you have multiple image views, you can use another method to avoid copying code everywhere.
First, add an unique tag for each image view. Avoid using 0 because the default tag is 0. So you will have image views with tags say 1 to 4.
Call this same method to all your image views so that this function is trigger by clicking on any of them
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
imageView.addGestureRecognizer(tapGestureRecognizer)
Handler looks like this
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
let image = UIImagePickerController()
image.delegate = self
image.sourceType = UIImagePickerControllerSourceType.photoLibrary
image.allowsEditing = false
let tappedImage = tapGestureRecognizer.view as! UIImageView
selected = tappedImage.tag
self.present(image, animated: true)
}
Finally in image pick delegate
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
if let imageView = self.view.viewWithTag(selected) as? UIImageView {
imageView.image = image
}
}
else {
//error
}
self.dismiss(animated: true, completion: nil)
}
The problem is that you have renamed the delegate method. If you do that, the method won't be recognized or called.
Another option to the selected answer is to extend UIImageView and have it adhere to UIImagePickerControllerDelegate / UINavigationControllerDelegate.
extension UIImageView: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
//handle error
return
}
image = selectedImage
picker.presentingViewController?.dismiss(animated: true)
}
func presentImagePicker(from viewController: UIViewController) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = .photoLibrary
picker.allowsEditing = false
viewController.present(picker, animated: true)
}
}
This is nice because you can then launch the image picker for any UIImageView in your app with one line, like so:
#IBAction func pickImage1(_ sender: UIButton) {
myImageView1.presentImagePicker(from: self)
}
Related
converted app from swift 3 to swift 4.2.
my app had a upload your profile image feature that is not working anymore and I am trying to figure out why. For now What I see is that
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo
didFinishPickingMediaWithInfo Is not being called after media was chosen
Here is my views full code:
import UIKit
class CameraMenuViewController: BaseViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var UserID:Int = 0
#IBOutlet weak var myImageView: UIImageView!
var callback : ((UIImage) -> ())?
#IBOutlet weak var btn_end: UIButton!
#IBOutlet weak var from_camera: UIBarButtonItem!
#IBOutlet weak var from_gallery: UIBarButtonItem!
#IBAction func btn_end_pressed(_ sender: UIButton) {
//
//self.openViewControllerBasedOnIdentifier("Home")
//let data = UIImagePNGRepresentation(myImageView) as NSData?
let image = myImageView.image!.pngData() as NSData?
//if let data = UIImagePNGRepresentation(myImageView) {
print("callback data")
let userDetails:Dictionary = (UserDefaults.standard.value(forKey: "myUserDetails") as? [String:Any])!
let UserID:Int = userDetails["UserID"] as! Int
print("UserID")
print(UserID)
print("is_selfie from callback")
//save profile image as NewUserID
UserDefaults.standard.set(image, forKey: String(UserID))
UserDefaults.standard.synchronize()
self.view.removeFromSuperview()
//}
}
#IBAction func btn_closer(_ sender: UIButton) {
//self.view.removeFromSuperview()
}
#IBAction func photofromLibrary(_ sender: UIBarButtonItem) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
picker.modalPresentationStyle = .popover
present(picker, animated: true, completion: nil)
picker.popoverPresentationController?.barButtonItem = sender
}
#IBAction func shootPhoto(_ sender: UIBarButtonItem) {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
print("photo shoot")
//UserDefaults.standard.set("selfie", forKey: "is_selfie")
UserDefaults.standard.set(true, forKey: "is_selfie")
UserDefaults.standard.synchronize()
DispatchQueue.main.async {
self.picker.allowsEditing = false
self.picker.sourceType = UIImagePickerController.SourceType.camera
self.picker.cameraCaptureMode = .photo
self.picker.modalPresentationStyle = .fullScreen
self.present(self.picker,animated: true,completion: nil)
}
} else {
noCamera()
}
}
let picker = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
picker.delegate = self
DispatchQueue.global(qos: .userInitiated).async
{
self.present(self.picker, animated: true, completion: nil)
}
let language = UserDefaults.standard.object(forKey: "myLanguage") as! String
if(language=="arabic"){
//from_camera.setTitle("كاميرا",for: .normal)
//from_gallery.text.setTitle("الصور",for: .normal)
btn_end.setTitle("إنهاء",for: .normal)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - Delegates
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
let chosenImage = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as! UIImage //2
myImageView.contentMode = .scaleAspectFit //3
myImageView.image = chosenImage //4
myImageView.layer.borderWidth = 1
myImageView.layer.masksToBounds = false
myImageView.layer.borderColor = UIColor.black.cgColor
myImageView.layer.cornerRadius = myImageView.frame.height/4
myImageView.clipsToBounds = true
callback?(chosenImage)
dismiss(animated:true, completion: nil)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}
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)
present(
alertVC,
animated: true,
completion: nil)
}
}
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertFromUIImagePickerControllerInfoKey(_ input: UIImagePickerController.InfoKey) -> String {
return input.rawValue
}
Please help me understand why didFinishPickingMediaWithInfo isn't getting called anymore
It appears as though the function declaration changed between Swift 3 and 4.2. This mustn't have been updated for you by the Swift Migrator Tool. One trick I do when this happens, to check what the correct function declaration is, is to use multiline comment syntax to comment out your current function (didFinishPickingMediaWithInfo in your case). Then you can start typing the function out again, and use Xcode autocomplete to ensure you have it correct. You can then copy the contents of the function you commented out to this new and correct function declaration.
Or - you could just look it up the documentation! According to the documentation on imagePickerController, the function should be declared as:
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
If you replace your function declaration with the above, it should get called again.
As Craig said you need to change delegate function declaration and also afterwards you need to update the following:
let chosenImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
These two changes combined should solve your issue.
i think the name off the function is update
this is my code in My app And work greate
extension FCViewController: UIImagePickerControllerDelegate
{
internal func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any])
{
if let photo = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
}
// Any Code Here ...
I've been looking for this answer online all morning long and I didn't find exactly what I needed. I want the user to add an image from his library and it would appear on the screen. I've managed to write the code that allows me to do that. However, I want that image to be saved. By that, I mean that I want the image selected to still appear after the user closes the app and reopens it. How can I do that?
Any help would be really appreciated :)
I've attached my code:
import UIKit
class Schedule: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet var imageView: UIImageView!
let imagePicker = UIImagePickerController()
#IBAction func addImage(sender: AnyObject) {
imagePicker.allowsEditing = false
// Only allow photos to be picked, not taken.
imagePicker.sourceType = .PhotoLibrary
presentViewController(imagePicker, animated: true, completion: nil)
}
// User picks image
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.contentMode = .ScaleAspectFit
imageView.image = pickedImage
}
dismissViewControllerAnimated(true, completion: nil)
}
// User cancels picking image action
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
}
}
You can do this using NSUserDefault, It will store your image data and you can retrieve it later. Change your viewDidLoad like this
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
if let imageData = NSUserDefaults.standardUserDefaults().objectForKey("image") as? NSData {
self.imageView.image = UIImage(data: imageData)
}
}
Now you need to store this imageData in NSUserDefault when you select image from UIImagePicker
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.contentMode = .ScaleAspectFit
imageView.image = pickedImage
let data = UIImagePNGRepresentation(pickedImage)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: "image")
NSUserDefaults.standardUserDefaults().synchronize()
}
dismissViewControllerAnimated(true, completion: nil)
}
Hope this will help you.
I am trying to make a simple "Profile" view that allows the user to change his picture. the image picker loads the gallery successfully and i choose the new image then write it to documents directory to load it in next launch, the problem is the imageview is not refreshing with the new image until i exit the app and relaunch again (only viewDidLoad works but viewWillAppear is loading the old image although it is overwritten!) any ideas?
import UIKit
class Profile: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var imagePicker:UIImagePickerController=UIImagePickerController()
var pickedImage:UIImage?
let filemgr = NSFileManager.defaultManager()
#IBOutlet weak var profilepic: UIImageView!
#IBOutlet weak var lblheight: UILabel!
#IBOutlet weak var lblwidth: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
profilepic.layer.borderWidth=1
profilepic.layer.borderColor=UIColor.blackColor().CGColor
let tapGestureRecognizer = UITapGestureRecognizer(target:self, action:Selector("imageTapped:"))
profilepic.userInteractionEnabled = true
profilepic.addGestureRecognizer(tapGestureRecognizer)
imagePicker.delegate=self
if profileImageExists()
{
pickedImage=UIImage(named: Operations.getDocumentsDirectory().stringByAppendingPathComponent("profile.png"))!
} else {
pickedImage=UIImage(named:"camera.png")!
}
profilepic.image=pickedImage
}
func imageTapped(img: AnyObject)
{
imagePicker.allowsEditing = false
imagePicker.sourceType = .PhotoLibrary
presentViewController(imagePicker, animated: true, completion:
{
self.lblheight.text="completed"
print ("completed image tab")
}
)
}
override func viewWillAppear(animated: Bool) {
pickedImage=UIImage(named: Operations.getDocumentsDirectory().stringByAppendingPathComponent("profile.png"))!
profilepic.image=pickedImage
}
// MARK: - UIImagePickerControllerDelegate Methods
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
profilepic.contentMode = .ScaleToFill
profilepic.image = pickedImage
if let data = UIImagePNGRepresentation(pickedImage) {
let filename = Operations.getDocumentsDirectory().stringByAppendingPathComponent("profile.png")
data.writeToFile(filename, atomically: true)
}
}
dismissViewControllerAnimated(true, completion: nil)
}
func profileImageExists() -> Bool
{
if let profileImage=UIImage(named: Operations.getDocumentsDirectory().stringByAppendingPathComponent("profile.png"))
{
return true
}
else
{
return false
}
}
}
Loading an UIImage with init(named:) caches the image. So as long as the image name does not change or the system is emptying the cache (for example when you restart the app) the image will be used from the cache and not loaded again.
Try to use init(contentsOfFile:) instead to load the image.
Try updating your imagePickerController method. You have used pickedImage as an instance variable and an local optional variable. I have used newImage instead.
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if let newImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
profilepic.contentMode = .ScaleToFill
profilepic.image = newImage
pickedImage = newImage
if let data = UIImagePNGRepresentation(newImage) {
let filename = Operations.getDocumentsDirectory().stringByAppendingPathComponent("profile.png")
data.writeToFile(filename, atomically: true)
}
}
dismissViewControllerAnimated(true, completion: nil)
}
I Have a circular framed UIImageView and I need to add a circular framed cropping tool for the UIImagePickerController, after the image is selected from a photo library. Very similar to Instagram's UIImagePicker's crop component. How do I add this type of component?
UPDATE
I've found this repo with a circular cropping tool https://github.com/ruslanskorb/RSKImageCropper
but can someone guide me on to how to implement this cropping tool with the UIImagePickerController after the user selects a photo from the photo library?
UPDATE
I am getting the following message in my debugger :
and the buttons in my crop view are disabled, meaning I cannot select them.. what message is the debugger relaying on to me?
here is my code:
#IBAction func chooseProfilePicture(sender: AnyObject) {
var myPickerController = UIImagePickerController()
myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(myPickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
var image : UIImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
editProfilePictureImageView.image = image
self.dismissViewControllerAnimated(false, completion: { () -> Void in
var imageCropVC : RSKImageCropViewController!
imageCropVC = RSKImageCropViewController(image: image, cropMode: RSKImageCropMode.Circle)
imageCropVC.delegate = self
self.navigationController?.pushViewController(imageCropVC, animated: true)
})
}
Example Demo
Yes you can add RSKImageCropper in your UIImagePickerController
define imagePicker
var imagePicker : UIImagePickerController!
in ViewDidLoad
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
self.presentViewController(imagePicker, animated: true, completion: nil)
Delegate methode :
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
{
var image : UIImage = (info[UIImagePickerControllerOriginalImage] as? UIImage)!
picker.dismissViewControllerAnimated(false, completion: { () -> Void in
var imageCropVC : RSKImageCropViewController!
imageCropVC = RSKImageCropViewController(image: image, cropMode: RSKImageCropMode.Circle)
imageCropVC.delegate =self
self.navigationController?.pushViewController(imageCropVC, animated: true)
})
}
see :
Kirit Modi's answer was exactly what I needed, although I needed to do one thing to make this work. For those that dont download the test project, make sure to implement your delegate methods:
Swift 3:
extension YourViewControllerClass: RSKImageCropViewControllerDelegate {
func imageCropViewControllerDidCancelCrop(_ controller: RSKImageCropViewController) {
_ = self.navigationController?.popViewController(animated: true)
}
func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect) {
self.avatarImageView.image = croppedImage
_ = self.navigationController?.popViewController(animated: true)
}
}
Swift 2:
extension YourViewControllerClass: RSKImageCropViewControllerDelegate {
func imageCropViewControllerDidCancelCrop(controller: RSKImageCropViewController) {
self.navigationController?.popViewControllerAnimated(true)
}
func imageCropViewController(controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect) {
self.avatarImageView.image = croppedImage
self.navigationController?.popViewControllerAnimated(true)
}
}
For Swift 2.2:
add delegate methods to your class:
class ViewController: UIViewController, UIImagePickerControllerDelegate, RSKImageCropViewControllerDelegate, UINavigationControllerDelegate
define imagePicker
var imagePicker : UIImagePickerController!
in viewDidLoad()
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePicker, animated: true, completion: nil)
And delegate methode :
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
let image : UIImage = image
picker.dismissViewControllerAnimated(false, completion: { () -> Void in
var imageCropVC : RSKImageCropViewController!
imageCropVC = RSKImageCropViewController(image: image, cropMode: RSKImageCropMode.Circle)
imageCropVC.delegate = self
self.navigationController?.pushViewController(imageCropVC, animated: true)
})
}
Of course it need to do bridge for objective C class
Oh, link to RSKImageCrop
I am building an app that allows user to add three pictures to threeUIImageViews
I added three buttons, for instance, when a user clicks on button one he should be able to add an image toUIImageView 1
but the image did not come to theUIImageView and I did not find any solution
sample of code:
#IBAction func imageOneBtn(sender: AnyObject) {
picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
picker.delegate = self
picker.allowsEditing = false
self.presentViewController(picker, animated: true, completion: nil)
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
imageViewOne.image = selectedImage
imageViewOne.contentMode = UIViewContentMode.ScaleAspectFit
picker.dismissViewControllerAnimated(true, completion: nil)
}
}
Thank you in advance
The code seems to be correct.
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage
Try removing the exclamation mark (!).
Try using imageViewOne.contentMode = .ScaleAspectFit
Also try using var instead of let selectedImage
In general Try this code
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
var selectedImage = info[UIImagePickerControllerOriginalImage] as UIImage
imageViewOne.contentMode = .ScaleAspectFit
imageViewOne.image = selectedImage
dismissViewControllerAnimated(true, completion: nil)
}
I have solved my problem, and this is the answer for anyone who may want to use it
import UIKit
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
#IBOutlet weak var oneImg: UIImageView!
#IBOutlet weak var twoImg: UIImageView!
#IBOutlet weak var threeImg: UIImageView!
var num=0;
func config() {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
imagePickerController.allowsEditing = true
imagePickerController.sourceType = .PhotoLibrary
presentViewController(imagePickerController, animated: true, completion: nil)
}
#IBAction func oneBtn(sender: AnyObject) {
num = 1
config()
}
#IBAction func twoBtn(sender: AnyObject) {
num = 2
config()
}
#IBAction func threeBtn(sender: AnyObject) {
num = 3
config()
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage;
if num == 1 { // switch can be used here
oneImg.image = selectedImage;
} else if (num == 2) {
twoImg.image = selectedImage
} else if (num == 3) {
threeImg.image = selectedImage
}
picker.dismissViewControllerAnimated(true, completion: nil)
}
}