I am coding as below for UIImagePickerController to get image from the photo library.
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
// Code here
var imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary;
imagePicker.mediaTypes = [kUTTypeImage]
imagePicker.allowsEditing = false
self.presentViewController(imagePicker, animated: true, completion: nil)
}
After selecting an image, I can show it on UIImageView, but I cannot get it's URL.
This is code I wrote to get it.
let url: NSString = info[UIImagePickerControllerReferenceURL] as NSString
var imageName:String = url.lastPathComponent
println("URL is \(imageName)")
let image = info[UIImagePickerControllerOriginalImage] as UIImage
profileImage.image = image
self.dismissViewControllerAnimated(true, completion: nil)
Here it gives nil and if I use UIImagePickerControllerEditedImage, it also crashes.
Can't we access URL directly, if not what is UIImagePickerControllerReferenceURL supposed to return?
How can I get the URL of the image so it could be sent to the server.
Thanks
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
if let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true) {
if paths.count > 0 {
if let dirPath = paths[0] as? String {
let readPath = dirPath.stringByAppendingPathComponent("yourNameImg.png")
var pickedimage = UIImage(CGImage: UIImage(contentsOfFile: readPath)!.CGImage, scale: 1.0, orientation: .Up)
UploadImagePreview.image = pickedimage
}
}
}
Note: We can set the image from url if the complete address is known. Here we are searching for the given image name in nsDocumentDirectory , finds out the complete image path and then set to image view.
Related
I am using UIImagePickerController to use my camera like so:
#objc func toggle() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
//Define UIImagePickerController variable
let imagePicker = UIImagePickerController()
//Assign the delegate
imagePicker.delegate = self
//Set image picker source type
imagePicker.sourceType = .camera
//Allow Photo Editing
imagePicker.allowsEditing = true
//Present camera
UIApplication.topViewController()?.present(imagePicker, animated: true, completion: nil)
}
}
Now I am trying to capture the image taken using the didFinishPickingMediaWithInfo method, I got this example online:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageUrl = info[UIImagePickerControllerOriginalImage] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
let image = info[UIImagePickerControllerOriginalImage]as! UIImage
let data = UIImagePNGRepresentation(image)
do
{
try data?.write(to: localPath!, options: Data.WritingOptions.atomic)
}
catch
{
// Catch exception here and act accordingly
}
UIApplication.topViewController()?.dismiss(animated: true, completion: nil);
}
But I changed UIImagePickerControllerReferenceURL to UIImagePickerControllerOriginalImage as UIImagePickerControllerReferenceURL is nil. but after I change that I get this fatal error:
Could not cast value of type 'UIImage' (0x1b6b02b58) to 'NSURL'
How do I save the image take from the camera? What am I doing wrong?
Write your code as following this will give you image.
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
UIImagePickerControllerOriginalImage return image not NSURL
Write following code to get image url in iOS 11. From iOS 11 UIImagePickerControllerImageURL is available, earlier there are UIImagePickerControllerMediaURL key to get image url.
if #available(iOS 11.0, *) {
if let imageURL = info[UIImagePickerControllerImageURL] as? URL {
print(imageURL)
}
} else {
if let imageUrl = info[UIImagePickerControllerMediaURL] as? URL {
print(imageUrl)
}
}
I hope this will help you.
The one who are searching for complete method to implement for Swift 4.2+
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage{
imageView.image = pickedImage
}
imgPicker.dismiss(animated: true, completion: nil)
}
This will return you the original image according to new syntax
For Image URL and Media URL, Use the respective
let imgURL = info[UIImagePickerController.InfoKey.imageURL]
let mediaURL = info[UIImagePickerController.InfoKey.mediaURL]
I want to share images to Instagram from my own iOS app and I am using Kingfisher throughout the project to download and cache images and show them in UIImageViews but this time I want to do something a little bit different.
Basically, I am getting a response from an API with the url of an image and I want to
Download the image to the library using the URL
There is a bunch of questions on this for objective-C using
UIImageWriteToSavedPhotosAlbum
but I am using Swift.
Rename it with .igo extension (instagram exclusive)
Not sure how to go about this, would depend on number 1.
Then I could share it doing something like
let image = UIImage(named: "downloadedImage")
let objectsToShare: [AnyObject] = [ image! ]
let activityViewController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
activityViewController.excludedActivityTypes = [ UIActivityTypeAirDrop, UIActivityTypePostToFacebook ]
self.presentViewController(activityViewController, animated: true, completion: nil)
or I could do it using the instagram hooks:
instagram://library?LocalIdentifier=\(localID)
Documentation on this is scarce specially for Swift. How can I go about this? a push in the right direction is all I need.
It sounds like you already know how to use Kingfisher and retrieving the UIImage from the URL. So what i'm about to provide is information for saving the image to the documents directory and retrieving it to share.
Retrieve the correct directory URL
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
Saving an image to that directory
func saveImage (image: UIImage, filename: String ){
print("Saving image with name \(filename)")
if let data = UIImagePNGRepresentation(image) {
let fullURL = getDocumentsDirectory().appendingPathComponent(filename)
try? data.write(to: fullURL)
}
}
Retrieving an image from the directory
func loadImageFromName(name: String) -> UIImage? {
print("Loading image with name \(name)")
let path = getDocumentsDirectory().appendingPathComponent(name).path
let image = UIImage(contentsOfFile: path)
if image == nil {
print("missing image at: \(path)")
}
return image
}
Sharing an image
func share(shareText shareText:String?,shareImage:UIImage?){
var objectsToShare = [AnyObject]()
if let shareTextObj = shareText{
objectsToShare.append(shareTextObj)
}
if let shareImageObj = shareImage{
objectsToShare.append(shareImageObj)
}
if shareText != nil || shareImage != nil{
let activityViewController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
present(activityViewController, animated: true, completion: nil)
}else{
print("There is nothing to share")
}
}
How to Use
let img: UIImage = UIImage() // Replace this with your image from your URL
saveImage(image: img, filename: "newImage.igo") //This is where you change your extension name
let newImage: UIImage = loadImageFromName(name: "newImage.igo") //Retrieve your image with the correct extension
share(shareText: "Image going to Instagram", shareImage: newImage) //Present Activity VC.
And as DFD pointed out, you can exclude certain items from the share VC to only allow what you need.
In my navigation controller, I have a UIBarButtonItem set to System item "Action". I then created the following IBAction code:
#IBAction func shareImage(_ sender: UIBarButtonItem) {
let context = CIContext()
let final = context.createCGImage(imgFinished, from: imgFinished.extent)
let shareImage = UIImage(cgImage: final!)
let vc = UIActivityViewController(activityItems: [shareImage], applicationActivities: [])
vc.excludedActivityTypes = [
UIActivityType.airDrop,
UIActivityType.assignToContact,
UIActivityType.addToReadingList,
//UIActivityType.copyToPasteboard,
//UIActivityType.mail,
//UIActivityType.message,
//UIActivityType.openInIBooks,
//UIActivityType.postToFacebook,
//UIActivityType.postToFlickr,
UIActivityType.postToTencentWeibo,
//UIActivityType.postToTwitter,
UIActivityType.postToVimeo,
UIActivityType.postToWeibo,
UIActivityType.print,
//UIActivityType.saveToCameraRoll
]
present(vc,
animated: true,
completion: nil)
vc.popoverPresentationController?.sourceView = self.view
vc.completionWithItemsHandler = {(activity, success, items, error) in
}
}
The excludedActivityTypes list is a complete/exhaustive list of available UIActivityTypes gleaned from code-complete or command-clicking on UIActivity type and going through the resulting struct. I uncomment those I wish to exclude - but leave them in for quick reference in the future. This will give you the popup you want.
I know I must be missing something in this code. If it has already been asked I don't know what term to search for. I searched about read picture in document folder blank, or empty. I knew it wasn't nil because Xcode said that it could not be nil for that type (UIImage).
I am able to use imagepicker to get a picture and display it in a UIImageView. When I save the UIImage into the Documents folder there is no error. However, when I read that saved image and try to display it in a UIImageView the picture is blank, or empty (it just shows the background color of the View.)
I am able to copy some pictures from the contents folder in the app into the Documents folder and they display properly. I went through and added print statements throughout the code to see if there was a place code was being skipped. I even wrote a function to list the filenames in the Documents folder. The names of the pictures are there, but the data for the picture that I would save doesn't seem to have been written.
func addNewPhoto() {
gotAPicture = true
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
let picker = UIImagePickerController()
picker.modalPresentationStyle = .CurrentContext
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
picker.delegate = self
presentViewController(picker, animated: true, completion: nil)
}
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
var newImage: UIImage
if let possibleImage = info[UIImagePickerControllerEditedImage] as? UIImage {
newImage = possibleImage
} else if let possibleImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
newImage = possibleImage
} else {
return
}
let imageName = NSUUID().UUIDString + ".jpg"
let imagePath = getDocumentsDirectory().stringByAppendingPathComponent(imageName)
if let pictureData = UIImageJPEGRepresentation(newImage, 0.9) {
pictureData.writeToFile(imagePath, atomically: true)
}
ChosenImage.image = newImage
picker.dismissViewControllerAnimated(true, completion: nil)
picker.delegate = nil
}
func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
I have checked the code, rewritten it, and started from scratch. I even followed coding examples from hackingwithswift.com in lesson 10 (as well as other tutorials). That lesson ended up working once I changed the .allowsEditing to false.
OK, here is the code that I use to display the picture
#IBOutlet weak var ChosenImage: UIImageView!
And, here is the code I am using to read the pictures in the Documents folder. It is in a different view controller and the outlet is called mainImage.
let fm = NSFileManager.defaultManager()
let path = getDocumentsDirectory()
let items = try! fm.contentsOfDirectoryAtPath(path as String)
imageList.removeAll()
currentImage = 0
for item in items {
if item.hasSuffix(".jpg") {
imageList.append(item)
}
}
mainImage.image = UIImage(named: imageList[currentImage])
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.swipeRight(_:)))
swipeRight.direction = .Right
self.view.addGestureRecognizer(swipeRight)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.swipeLeft(_:)))
swipeLeft.direction = .Left
self.view.addGestureRecognizer(swipeLeft)
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.swipeUp(_:)))
swipeUp.direction = .Up
self.view.addGestureRecognizer(swipeUp)
What is causing the data of the UIImage to not get written along with the filename? I am sure that I missed something.
Thanks.
You should not use this kind of initialisation for image like let image = UIImage(named: <#imageName#>), because this kind of initialisation better use only for images that exists in your application bundle. I suppose that you will suit with method like let image = UIImage(contentsOfFile: <#imagePath#>) for clearance that you load images, that you persist earlier.
However, you problem is simple, when you get your contents of directory, the output will like that
21AB15AE-D69A-416B-AE93-6DC334E41F91.jpg
6CB9FA7B-FF20-4D60-B7EB-B44300C85AF9.jpg
86508AEC-AE8B-4FB8-8CA5-307DF58E959A.jpg
9C90944E-87EE-4B41-BA99-A6A8171402AC.jpg
AC2BC0D4-CA51-4A24-9D80-87F8736A72A7.jpg
B0C772A6-8354-4C7C-B23B-7414123E52FB.jpg
B10FE95C-E017-411C-BAD1-986A6090F463.jpg
DCB4B0C9-DDB4-4188-8DF7-0ABFD2FD76CB.jpg
EEDDCABD-A707-4CAA-9AF7-5009EAA57FA8.jpg and so on...
That leads to main problem - you try to load images just by referring to it only their name, and that produce nil-image as result. To load image you should specify full path to image (full-path will work both for contentsOfURL and named initializers)
I'd create simple project, you can get it here
In my app, I have a button with which I open the Gallery as below:
#IBAction func selectPhoto() {
let photoPicker = UIImagePickerController()
photoPicker.delegate = self
photoPicker.sourceType = .PhotoLibrary
self.presentViewController(photoPicker, animated: true, completion: nil)
}
I let the user select a photo and save it:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
photoImageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
let fileName:String = "logo.png"
let arrayPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let pngFileName = arrayPaths.stringByAppendingPathComponent(fileName) UIImagePNGRepresentation(photoImageView.image!)!.writeToFile(pngFileName, atomically:true)
imageSave.setObject(fileName, forKey: "pngFileName")
self.dismissViewControllerAnimated(false, completion: nil)
}
Then from View controller, the pictures saved is shown everytime the user gets to the scene using below code.
override func viewDidLoad() {
super.viewDidLoad()
if imageSave.stringForKey("pngFileName") != nil
{
let path = NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let fileName = NSUserDefaults.standardUserDefaults()
.stringForKey("pngFileName")
let imagePath = path.stringByAppendingPathComponent(fileName!)
let image = UIImage(contentsOfFile: imagePath )
photoImageView.image = image
}
Problem : When the image loads back onto the UIImageView, the orientation of the picture is sometimes rotated right by 90 degrees, sometimes rotated left by 90 degrees or sometimes shown as it was saved.
Please let me know what I am doing wrong here. Any help would be appreciated. Thanks
I had the same problem, because of different rect sizes where the photo is shown. You could do a trick and save instead of the original image a copied version. This will discard the rotation problem, which is actually a fitting issue.
let imageName = info[UIImagePickerControllerOriginalImage] as! UIImage
let thumb1 = UIImageJPEGRepresentation(imageName, 0.8)
btnImageView.image = UIImage(data: thumb1!)
This is just a quick and dirty answer, but worked for me. :-)
I am trying to load an image that I have saved inside Document directory. If I print the path I can see that there is the image however, when I trie to assign the path to a UIImage the app crashes:
static func callSavedProfileImage() -> UIImage{
//let profilePictureUser = NSUserDefaults.standardUserDefaults()
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
var newImage = UIImage!()
if paths.count > 0
{
let dirPath = paths[0]
let readPath = (dirPath as NSString).stringByAppendingPathComponent("ProfilePic.png")
print(readPath) ///var/mobile/Containers/Data/Application/C9F738C1-F747-4C1D-ADBE-251F168444D4/Documents/ProfilePic.png
let savedProfilePicture = readPath
if let savedImage = UIImage(contentsOfFile: savedProfilePicture) {
newImage = savedImage
}
}
print(newImage)
return newImage
}
Any idea why?
var newImage = UIImage!()
should be
var newImage = UIImage()
When you declare UIImage!() it creates an implicitly unwrapped Optional which will crash if unwrapped while nil.
Just remove the ! to create a normal UIImage, then it won't crash if the image can't be found.