Display image from URL in swift, unwrapping error - url

I'm trying to display image to imageView from URL. I successfully done it using synchronous method in a simple project. But this application is used for online store, so I took product information and image URL from a JSON file. which I'm sure I was successfully stored all the data in a product array. But the problem I'm facing is this:
fatal error: unexpectedly found nil while unwrapping an Optional value
Here is the code.
// UnWrapping imageURL
let url:NSURL? = NSURL(string: actualCurrentProduct.imageURL)
if let actualURL = url {
let imageData = NSData(contentsOfURL: actualURL)
if let actualImageData = imageData {
self.productImageView.image = UIImage(data: actualImageData)
}
}
It highlighted in this particular code.
self.productImageView.image = UIImage(data: actualImageData)
Anybody have any idea why? Really appreciated it.

I managed to display the image successfully from URL with this code. I started the project from the scratch and for the display image part, here is my code.
let imageURL = NSURL(string: actualCurrentProduct.imageURL)
if let actualImageURL = imageURL {
let imageData = NSData(contentsOfURL: actualImageURL)
if let actualImageData = imageData {
let image = UIImage(data: actualImageData)
if let actualImage = image {
self.productImage.image = actualImage
}
}
}
Finally....

Related

There is an optional error while downloading the image from the storage, I have converted the string to URL

There is an error for optional while downloading the image from the firebase storage, I am converting the string to URL to download the image
here is the code where the error is occuring , if any more code is required do let me know
let imageUrl = URL(string: post._postuserprofileImagUrl)
ImageService.getImage(withURL: imageUrl) { image in
self.profileImageView.image = image
}
You have to (safely) unwrap the URL instance
if let imageUrl = URL(string: post._postuserprofileImagUrl) {
ImageService.getImage(withURL: imageUrl) { image in
self.profileImageView.image = image
}
}
Or even (if postuserprofileImagUrl is optional, too)
if let userprofileImagUrl = post._postuserprofileImagUrl,
let imageUrl = URL(string: userprofileImagUrl) {
ImageService.getImage(withURL: imageUrl) { image in
self.profileImageView.image = image
}
}

Swift Grand Central Dispatch Queues and UIImages

I know this type of question has been asked 1e7 times but I have come across a specific issue that I don't think has been covered/is blatantly obvious but I am too novice to fix it on my own.
I have the following code snippet within my cellForRowAt method in a TableViewController:
let currentDictionary = parser.parsedData[indexPath.row] as Dictionary<String,String>
let urlString = currentDictionary["media:content"]
if urlString != nil {
let url = NSURL(string: urlString!)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url! as URL) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
cell.thumbnailImageView.image = UIImage(data: data!)
}
}
}
Which executes fine, downloads the images and assigns them to the UIImageView of each tableViewCell.
There is a finite delay when scrolling the table as the images are downloaded 'on the fly' so to speak.
What I want to do is pre-download all these images and save them in a data structure so they are fetched from URL's less frequently.
I have tried the following implementation:
var thumbnail = UIImage()
for item in parser.parsedData {
let currentDictionary = item as Dictionary<String,String>
let title = currentDictionary["title"]
let link = currentDictionary["link"]
let urlString = currentDictionary["media:content"]
let url = NSURL(string: urlString!)
if urlString != nil {
let url = NSURL(string: urlString!)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url! as URL)
DispatchQueue.main.sync {
thumbnail = UIImage(data: data!)!
}
}
}
var newsArticle: News!
newsArticle = News(title: title!, link: link!, thumbnail: thumbnail)
news.append(newsArticle)
Where news is my data structure. This code also executes fine, however each thumbnail is a 0x0 sized image, size {0, 0} orientation 0 scale 1.000000, according to the console output.
Does anyone have any ideas how to download these images but not immediately assign them to a UIImageView, rather store them for later use?
The problem is that you create your newsArticle before the global dispatch queue even started to process your url. Therefore, thumbnail is still the empty UIImage() created in the very first line.
You'll have to create the thumbnail inside the inner dispatch closure, like:
for item in parser.parsedData {
guard let currentDictionary = item as? Dictionary<String,String> else { continue /* or some error handling */ }
guard let title = currentDictionary["title"] else { continue /* or some error handling */ }
guard let link = currentDictionary["link"] else { continue /* or some error handling */ }
guard let urlString = currentDictionary["media:content"] else { continue /* or some error handling */ }
guard let url = URL(string: urlString) else { continue /* or some error handling */ }
DispatchQueue.global().async {
if let data = try? Data(contentsOf: url) {
DispatchQueue.main.sync {
if let thumbnail = UIImage(data: data) {
let newsArticle = News(title: title, link: link, thumbnail: thumbnail)
news.append(newsArticle)
}
}
}
}
}
By the way, your very first code (cellForRow...) is also broken: You must not reference the cell inside the dispatch closure:
DispatchQueue.main.async {
// Never do this
cell.thumbnailImageView.image = UIImage(data: data!)
}
Instead, reference the IndexPath, retrieve the cell inside the clousure, and go on with that cell. But as you already mentioned, there are many many entries on stackoverflow regarding this issue.

how to load an image from the url getting from server

I am having and imageView and I am getting the userData from the server when loggedIn in the userData I have a parameter for "profilePic":"penguins.jpg". now I am adding the domain like "http://.....(self.userData.value(forKey: "profilePic")!)" and saving this value into a string variable to store and when I am accessing the value and trying to convert the url into data and adding to imageView.image it is throwing : unexpectedly found nil while unwrapping an optional value..
All my other userData like name,address,phoneNumber are showing fine except for Image.
My Code:
here are the some of the many ways I tried:
way:1
let ad : AppDelegate = UIApplication.shared.delegate as! AppDelegate
let imageUrlString = ad.userImagePath
let imageUrl:URL = URL(string: imageUrlString)! // it is throwing error here(: unexpectedly found nil while unwrapping an optional value)
DispatchQueue.global(qos: .userInitiated).async {
let imageData:NSData = NSData(contentsOf: imageUrl)!
DispatchQueue.main.async {
let image = UIImage(data: imageData as Data)
self.profileImage.image = image
}
}
way:2
if let url = NSURL(string: ad.userImagePath) {
if let data = NSData(contentsOf: url as URL){
if let imageUrl = UIImage(data: data as Data) {
profileImage.image = imageUrl
}
}
}
I have tried different ways to solve this, can't figure out what is my mistake.. finally I am here.. Please someone help he...

How to use value of variable in swift iOS

I'm tyring to learn swift. I have a simple demo project. I have a variable, and its value is a url which points to an image. when I try to print this value (the value of the URL encoded in the variable), it works fine, but when I try to use that same variable's value at runtime, it fails. What should I do?
var picurl : String!
profilePicView.image = UIImage(named: "\(picurl)") // image is not showing with pic url
print("User name --- \(Username)")
print("User picurl --- \(picurl)")// but here value is printed.
Thank you.
if you are fetch the image from URL use this
if let imageUrl = NSURL(string: \(picurl)) {
if let imageData = NSData(contentsOfURL: imageUrl) {
profilePicView.image = UIImage(data: imageData)
}
}
load from locally use this
if let img = UIImage(named: "\(picurl)") {
profilePicView.image = img
}

UIImage Bad instruction

Looking through the forums I have found that this issue is one that shows its head every now and then. And apparently doing so in a wide scope of different cases. None that I have managed to find seem to be similar to mine though.
I'm halfway through my program (lesson) in creating a usable twitter application. Testing it currently runs the program as it should, without any errors. But when I select an account the program crashes and an error message shows up at the image method which is supposed to load the avatar of the selected user. I assume that it is not able to retrieve a valid image or fetch data at all (because of the line ImageData = (NSDATA?) nil in the debug area), but I am by no means sure of anything, let alone how to or where to find a solution. If I am searching with the wrong keywords then please let me know. (I am searching for exc_bad_instruction and uiimage error) Thanks in advance.
I'll post the snippet of code where the issue presents itself below and what is shown in the debug area below that.
if let cachedImage = image {
cell.tweetUserAvatar.image = cachedImage
}
else {
cell.tweetUserAvatar.image = UIImage(named: "camera.png")
queue?.addOperationWithBlock() {
let imageURL = NSURL(string: imageURLString) as NSURL!
let imageData = NSData(contentsOfURL: imageURL) as NSData?
let image = UIImage(data: imageData!) as UIImage? // EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subode=0x0)
if let downloadedImage = image {
NSOperationQueue.mainQueue().addOperationWithBlock(){
let cell = tableView.cellForRowAtIndexPath(indexPath) as! TweetCell
cell.tweetUserAvatar.image = downloadedImage
}
self.imageCache?.setObject(downloadedImage, forKey: imageURLString)
}
}
}
Debug area:
imageURLString String
"http://pbs.twimg.com/profile_images/465756113825067008/8jH2nZO0_normal.png"
tableView UITableView 0x00007fc52481b400
indexPath NSIndexPath * 0xc000000000000016
self Chapter7_8___Social_App.FeedViewController 0x00007fc5235f5ef0
imageURL NSURL! "http://pbs.twimg.com/profile_images/465756113825067008/8jH2nZO0_normal.png"
imageData NSData? nil None
image UIImage? 0x000000010ee778dd
downloadedImage UIImage
I had this issue as well and found that my image was being initialized with bad data. This is to say that the image I requested from the server did not exist and the server sent back a response which could not be converted into an UIImage.
To mitigate this you can do the following:
if let cachedImage = image {
cell.tweetUserAvatar.image = cachedImage
}
else {
cell.tweetUserAvatar.image = UIImage(named: "camera.png")
queue?.addOperationWithBlock() {
let imageURL = NSURL(string: imageURLString) as NSURL!
let imageData = NSData(contentsOfURL: imageURL) as NSData?
if let image = UIImage(data: imageData!) {
let downloadedImage = image
NSOperationQueue.mainQueue().addOperationWithBlock(){
let cell = tableView.cellForRowAtIndexPath(indexPath) as! TweetCell
cell.tweetUserAvatar.image = downloadedImage
}
self.imageCache?.setObject(downloadedImage, forKey: imageURLString)
}
}
}
What I have done above is changed
let image = UIImage(data: imageData!) as UIImage?
if let downloadedImage = image {
...
...
}
To:
if let image = UIImage(data: imageData!) {
let downloadedImage = image
...
...
}
In this way I have checked that the image was able to be created successfully. If the image is not able to be created then the code will not execute and you will not receive an error.
If you expect an image to be at the url you specified in 'imageURLString' then I would suggest that you check the url you are using.
I also noticed that you did not get any data back which is why you could not create the UIIMage. You can test to see if this is the case with the following:
let imageData = NSData(contentsOfURL: imageURL) as NSData?
if imageData != nil {
Do More Stuff
...
{
I hope my answer was helpful. If you have any questions feel free to leave a comment and I'll do my best to answer them.
More Info Here:
This question & answer also provides methods on how to handle the case when the UIImage cannot be created from the data provide.

Resources