I have hooked to Selection changed event of NSTableView.I need to display the selected image in the imageview
func tableViewSelectionDidChange(_ notification: Notification)
{
let table = notification.object as! NSTableView
print(fileArray[table.selectedRow].path);
img_view.image=NSImage(named: NSImage.Name(rawValue: fileArray[table.selectedRow].path))
}
The console prints
/Users/myname/Downloads/435_v9_bc.jpg
But the imageview does not display the image.
Update 1:
print(fileArray[table.selectedRow].path);
img_view.image=NSImage(byReferencing: URL(string: fileArray[table.selectedRow].path)!)
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Console still prints
/Users/myname/Downloads/123_1 (1).jpeg
URL(string: is the wrong API, for file system paths you have to use URL(fileURLWithPath.
img_view.image = NSImage(byReferencing: URL(fileURLWithPath: fileArray[table.selectedRow].path))
However fileArray[table.selectedRow] seems to be already an URL so there is a still easier way
img_view.image = NSImage(contentsOf: fileArray[table.selectedRow])
Related
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.
I am trying to load and display a gif file inside a NSImageView but nothing appears when I run the project.
I have try to link the gif file with NSImageView using url, data or named, but it does not work.
func applicationDidFinishLaunching(_ aNotification: Notification)
{
let url = Bundle.main.url(forResource: "RSynchro-Gif", withExtension: "gif")!
let data = try! Data(contentsOf: url)
gifBoutton.image = NSImage(data: data)
}
or
func applicationDidFinishLaunching(_ aNotification: Notification)
{
let url = Bundle.main.url(forResource: "RSynchro-Gif", withExtension: "gif")!
gifBoutton.image = try! NSImage(data: Data(contentsOf: url))
}
or
func applicationDidFinishLaunching(_ aNotification: Notification)
{
let icon = NSImage(named: NSImage.Name(rawValue: "RSynchro-Gif"))
imageGif.image = icon
imageGif.animates = true
}
None of them works but if I replace the .gif file with a .png, it works.
Anyone to show me the right way?
Thanks.
(See the edit to my answer below. My initial answer was outdated and therefore wrong.)
I don't believe there is native support for GIF image type in Mac OS. (I know for a fact there isn't in iOS, where I do most of my work these days, and am fairly sure the same holds true for Mac OS. I know Mac OS didn't support GIF as of about 3 years ago.)
EDIT:
Apparently I'm wrong. It looks like you can load the first frame of a GIF image if you put the image in your app's bundle directly rather than into your assets catalog. If you create an image set in your asset catalog and drag a GIF into that it appears to work in Xcode but the image doesn't load. (I tried it for both a Mac app and an iOS app and the results are the same.)
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.
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)
}
}
I create a watchKit app/extension of my app. I use this func to load the data into the WKInterfaceTable:
// Load table into the data
func loadTableData() {
let sharedDefault = NSUserDefaults(suiteName: "group.com.Devpr.App")
let numberItems = sharedDefault?.objectForKey("numberItems") as? Int
tableView.setNumberOfRows(numberItems!, withRowType: "Cell")
var i = 0
let task = sharedDefault?.objectForKey("\(i)WK") as? String
let row = tableView.rowControllerAtIndex(i) as! TableRowObject // Get a single row object for the current item
row.lblTblRowItem.setText(task) // Set the row text to the corresponding item
i++ // Move onto the next item
}
The app is crashing in this line of the function: let row = tableView.rowControllerAtIndex(i) as! TableRowObject with this error: fatal error: unexpectedly found nil while unwrapping an Optional value. I really can't find anything which is nil.
Image after the crash:
I hope someone of you can help me to solve this. Thanks a lot for you're help!
If numberOfItems is 0, tableView.rowControllerAtIndex(i) can be nil.