How can I get an URL from UIImage? I've got an image from iPhone library and I resize it and I don't want to save the new image but I want to get it's URL.
You say you don't want to save it, but if you need a URL for a UIImage, you can easily save a temp copy to get the URL that you need.
For newer swift 5:
// Create a URL in the /tmp directory
guard let imageURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("TempImage.png") else {
return
}
let pngData = image.pngData();
do {
try pngData?.write(to: imageURL);
} catch { }
Now you can use the URL to share the image to social media or whatever you need to do with it.
For previous Swift versions:
// Create a URL in the /tmp directory
guard let imageURL = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("TempImage.png") else {
return
}
// save image to URL
do {
try UIImagePNGRepresentation(myImage)?.write(to: imageURL)
} catch { }
See here for more.
UIImage has no URL or file information. It's just a collection of bytes representing the pixel color data. If you get the UIImage from a UIImagePicker then you can get the URL to the original image in the asset library. But you must get this URL in the image picker delegate method and you must keep track of it separately from the UIImage object.
Edit - based on the OP's comment, this is not the information being requested.
What you are looking for is the UIImagePickerControllerReferenceURL parameter provided by the delegate callback in the info dictionary. What you need to do is:
NSURL* imageURL = [info objectForKey:UIImagePickerControllerReferenceURL];
And it would look something like this:
assets-library://asset/asset.JPG?id=SOME_GUUID&ext=JPG
You could use this latter to refer back to the same image you got in the UIImage* in the callback.
You could subclass UIImage and create an override initWithURL: to save the URL to a created property... something like this.
+ (id) initWithURL:(NSURL*)url
{
[super initWithURL:url];
self.url = url;
}
Related
I am able to successfully save my image in user defaults as I use my app and retrieve it just fine but am having trouble figuring out how to retrieve it in a simple via init(). In my example it will returns the AppValue.avatar (my default image) but won't return the stored image. It can't find the previously stored image so it substitutes my default image it fails because I have UIImage in the published variable. I think it must have to be retrieved as data but if I change UIImage in the init() to Data Xcode is not happy.
class UserSettings: ObservableObject {
#Published var avatar: UIImage {
didSet {
/// Convert to data using .pngData() on the image so it will store. It won't take the UIImage straight up.
let pngRepresentation = avatar.pngData()
UserDefaults.standard.set(pngRepresentation, forKey: "avatar")
printSave(forKey: "avatar", value: avatar)
}
}
init() {
self.avatar = UserDefaults.standard.object(forKey: "avatar") as? UIImage ?? AppValue.avatar
}
}
It's simply a matter of keeping mental track of what type a thing is.
You saved the image as its pngData (correctly). This is not a UIImage; it is a Data. Your pngRepresentation, which is what gets saved, is a Data.
Hence when you retrieve the image and say as? UIImage, that test fails. It is not a UIImage. It's a Data.
Therefore, fetch data(forKey:) (or say as? Data instead of as? UIImage). Now you have the Data. then call UIImage.init(data:) to retrieve the image.
I'm struggling to download pictures from firebase storage to an UIImage in swift 5.
I can well upload them. When I tried to retrieve picture, the UIImage display a black screen.
here my function which return the UIImage
import UIKit
import Firebase
func getImageEvent (imagePath : String) -> UIImage? {
var myImage : UIImageView?
//Access to the storage
let storageRef = Storage.storage().reference(withPath: imagePath)
storageRef.getData(maxSize: 1 * 1024 * 1024) {(data, error) in
if let error = error {
print(error.localizedDescription)
return
}
if let data = data {
print(data.description)
myImage?.image = UIImage(data: data)
}
}
return myImage?.image
}
//Call the function
getImageEvent (imagePath :"9U4BoXgBgTTgbbJCz0zy/eventMainImage.jpg")
In the console, I can well see a value for print(data.description).
By default, there is an image in the UIImageView. When call the function, the default image is replaced by a black screen.
Could you please help me to understand the mistake ?
many thanks
There's a number of ways to go about this but a brief description of the issue first:
The return statement within the closure will execute way before that image is downloaded - Firebase functions are asynchronous and code has to be crafted in a way that allows for time to download and get data from the internet. So - don't try to return data from asynchronous functions.
Here's the code re-written with a completion handler. That handler will be called only after the image is fully downloaded.
func getImageEvent (imagePath: String, completion: #escaping(UIImage) -> Void) {
var myImage : UIImageView?
let storageRef = Storage.storage().reference(withPath: imagePath)
storageRef.getData(maxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
print(error.localizedDescription)
return
}
if let data = data {
if let myImage = UIImage(data: data) {
completion(myImage)
}
}
}
}
and the key is how to call that function. Note this code awaits the data (UIImage) to be passed back to it within it's closure and lets you know that getting the image was complete.
self.getImageEvent(imagePath: "9U4BoXgBgTTgbbJCz0zy/eventMainImage.jpg", completion: { theImage in
print("got the image!")
})
You should add additional error checking in case the image was not downloaded or myImage was nil. Passing back an error message along with the nil myImage would be one option, or making the object passed back as an optional and then checking for nil within self.downloadImageAtPath would be another.
To complete the solution, below the code used to in tableView to get picture in a particular cell
getImageEvent(imagePath: myArray[indexPath.row].partyImagePath) { (image) in
cell.partyImage.image = image
}
How to load image from web service in swift without memory warning. What is the most ideal way of loading image from web service? I tried with SDWebImage but my app shows memory recieved warning.
You can simply use NSData and UIImage like this
guard let
url = NSURL(string: "PUT_THE_WEBSERVICE_CALL_HERE"),
data = NSData(contentsOfURL:url) else { return }
let image = UIImage(data: data)
I'm trying to get the thumbnail of a several files and it should return as an NSDictionary yet keeps returning nil. For instance, this works:
try aURL.getResourceValue(&thumbnails, forKey:NSURLNameKey)
if let thumbnail = thumbnails as? NSString
{
print(thumbnail)
}
But this doesn't (which is what I'm trying to do):
try aURL.getResourceValue(&thumbnails, forKey:NSURLThumbnailDictionaryKey)
if let thumbnail = thumbnails as? NSDictionary//Dictionary<String, NSImage>//Doesn't work either
{
print(thumbnail)
}
Anybody have any idea what the problem is here? Thanks in advance.
Alright so I've made some handlers and classes to grab data from a URL, its all returning fine, I've checked the URLs are valid and everything.
Anyways, I'm trying to do an NSData(contentsOfURL) on a stored URL in my class for a UIViewController. I'm successfully printing out String Variables like name, type, description, but I'm having difficulty displaying an UIImage into a Image View on the ViewController.
Here is my Code, it's run when the View loads:
func configureView() {
// Update the user interface for the detail item.
if let card = detailCard {
title = card.cardTitle
//Assign Elements
detailDescriptionLabel?.text = card.description
typeLabel?.text = card.cardType
cardTitleLabel?.text = card.cardTitle
costLabel?.text = card.cardCost
print(card.cardImageURL)
if let url = NSURL(string: card.cardImageURL){
let data = NSData(contentsOfURL: url)
imageView.image = UIImage(data: data!)// <--- ERROR HERE: EXC_BAD_INSTRUCTION
}
//Print Log
//print(card.logDescription)
}
}
Like the comment says above, I get the error on the imageView.image = UIImage(data: data!) line:
Thread 1: EXC_BAD_INSTRUCTION
Here is the code for cardImageURL:
var cardImageURL: String {
return String(format: "http://testyard.example.net/display/images/cards/main/%#", image)
}
//This is a computed variable when a "Card" class object is created.
It returns the correct url in a string:
http://testyard.example.net/display/images/cards/main/armor-of-testing.jpg
I've used this code elsewhere, and it worked fine, why is it throwing errors here?
Thanks in advance.
Are you sure the data being downloaded is an image? You should probably use this line:
if let image = UIImage(data: data)`
This should stop the error, though you might need to test that your data actually contains an image.