Swift NSURL getResourceValue as NSURLThumbnailDictionaryKey returns nil - swift

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.

Related

Swift UITableViewCell - Cell Image changes if I scroll down too fast, but only on the first attempt

I am parsing a JSON within my viewDidLoad method. One of the keys within this JSON is the image URL, which goes into a a string array called "allCImages"
This is just a string. Therefore to populate the image into the cell, in my cellForRowAt method, I have the following:
cell.vcCellImage.downloadImage(from: allCImages[indexPath.section])
Note: vcCellImage is the IBOutlet of my cell image view.
The "downloadImage" method is part of the following extension:
extension UIImageView {
func downloadImage(from imgURL: String!) {
let theUrl = URLRequest(url: URL(string: imgURL)!)
// set initial image to nil so it doesn't use the image from a reused cell
image = nil
// check if the image is already in the cache
if let imageToCache = vc1ImageCache.object(forKey: imgURL! as NSString) {
self.image = imageToCache
print("Image is in Cache")
return
}
// download the image asynchronously
let task = URLSession.shared.dataTask(with: theUrl) { (data, response, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
// create UIImage
let imageToCache = UIImage(data: data!)
// add image to cache
vc1ImageCache.setObject(imageToCache!, forKey: imgURL! as NSString)
self.image = imageToCache
}
}
task.resume()
}
This is working almost perfectly. For example:
1) If I scroll down my tableview slowly, all the cells contain the correct image
2) If I scroll up my tableview, slowly or quickly, all the cells contain the correct image. This is proven by the fact that my console is printing the following:
Image is in Cache
Image is in Cache
Image is in Cache
I.e, the tableview is getting my image from the cache (since to scroll up, I must have scrolled down before)
3) The issue is if I scroll down my tableview really quickly, on the first attempt. Since the image has not cached yet, the cell will display the wrong image, before changing to the correct image. Classic problem
Therefore I am missing this small piece of logic. How to resolve this?
EDIT: I tried this but the issue remains:
class VCTableViewCell: UITableViewCell {
override func prepareForReuse() {
super.prepareForReuse()
vcCellImage.image = nil
}
This occurs because of
1- cell dequeueing : cells are re-used inside the tableView
2- when you scroll before a request happens it may cause a new 1 with same url
Best option is using SDWebImage
I have faced the similar issue.
I have fixed this issue by cancelling the image request in the prepareForReuse method.
Can you try the same?
first off all if you are appending your api or any data like this just remove this
var arr = [string]()
viewDidLoad()
{
arr.append("s","sd","sd)
}
accept this
var arr = [string]()
viewWillAppear()
{
arr.removeAll()
//call api
//append Data
arr.append("s","sd","sd)
}
I have similar problem then I solve it like this, may be it helpful for you also.

Updating thumbnail of UIDocument in iCloud

I have a UITableViewController which displays a list of NSMetaDataItems which are connected to a StoryDocument which subclasses UIDocument. Each StoryDocument has a UIImage property called image. Each row shows it's thumbnail.
I've overridden fileAttributesToWrite(to: URL, for: UIDocumentSaveOperation) to save the thumbnail as follows:
override func fileAttributesToWrite(to url: URL, for saveOperation: UIDocumentSaveOperation) throws -> [AnyHashable : Any] {
let thumbnailSize = CGSize(width: 1024, height: 1024)
if let thumbnail = image?.at(targetSize: thumbnailSize) {
return [
URLResourceKey.hasHiddenExtensionKey : true,
URLResourceKey.thumbnailDictionaryKey : [
URLThumbnailDictionaryItem.NSThumbnail1024x1024SizeKey : thumbnail
]
]
} else {
return [:]
}
}
I set the thumbnail in func tableView(_:, cellForRowAt:) where url is the url metadataItems.value(forAttribute: NSMetadataItemURLKey)
do {
var thumbnailDictionary: AnyObject?
let nsurl = url as NSURL
try nsurl.getPromisedItemResourceValue(&thumbnailDictionary, forKey: URLResourceKey.thumbnailDictionaryKey)
cell.thumbnailImageView.image = thumbnailDictionary?[URLThumbnailDictionaryItem.NSThumbnail1024x1024SizeKey] as? UIImage
} catch {
cell.thumbnailImageView.image = nil
}
If I change the StoryDocument's image in a detail view and then return to the UITableViewController, the original thumbnail (unchanged) is still shown, even though I'm telling the UITableView to reloadData(). The image only updates about 10 seconds later, when the next .NSMetadataQueryDidFinishGathering or .NSMetadataQueryDidUpdate notification comes in. Is there a good way to get the recently changed thumbnail for the cell rather than the old one?
I'm using Swift 4, although I expect I could adapt suggestions in Swift 3 too.
Many thanks in advance.

Getting Image from URL for UIView [Swift]

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.

Show Image from URL in detailView after selection in tableView

I have a tableView which display a list of traffic-cameras parsed from a XML file. When I select a cell, it sends the ImageURL, Roadname, Coordinates etc. via the prepareForSegue method.
In my detailviewcontroller I declare the incoming values as the following:
var selectedFeedURL = String()
var selectedFeedRoadname = String()
var selectedFeedLongitude = String()
var selectedFeedLatitude = String()
I have no problem printing all the values into the log or set it as labels. The problem occurs when I try to load the selectedFeedURL (which is the URL to the image, i.e: http://webkamera.vegvesen.no/kamera?id=559847) and set it to my imageView..
In my viewDidLoad, I have the following code, which should download the image and set it to my imageView named cameraImageView.
if let url = NSURL(string:"\(selectedFeedURL)") {
if let data = NSData(contentsOfURL: url){
print("Suksess")
cameraImageView.image = UIImage(data: data)
}
}
My imageView stays empty and I doesn't get any errors or complains in the debug area. If I print out the selectedFeedURL, the link is there.
The weird part is that if I change
NSURL(string:"\(selectedFeedURL)")
to
NSURL(string:"http://webkamera.vegvesen.no/kamera?id=559847")
Basically changing the variable to a camera URL, it works perfectly.
Soo... any suggestions on what the problem might be?
Much appreciated :)
If there are white spaces and newline characters at the start and end of your URL string, it won't work.
Try:
selectedFeedURL = selectedFeedURL.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
if let url = NSURL(string: selectedFeedURL) {
if let data = NSData(contentsOfURL: url){
print("Suksess")
cameraImageView.image = UIImage(data: data)
}
}

How to get URL from UIImage

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;
}