Error always thrown loading UIImage from URL [duplicate] - ios

This question already has answers here:
Transport security has blocked a cleartext HTTP
(29 answers)
Closed 6 years ago.
When I try to load an image from a URL I always get an error despite the fact that I know that there is a URL that contains a valid .jpg image.
mainImageView.image = try UIImage(data: Data(contentsOf: URL(fileURLWithPath: artworkURL)))
I also tried these solution but the line where I initialise the UIImage still throws an error.
Example of data in artworkURL:
http://is1.mzstatic.com/image/thumb/Music/v4/ef/97/95/ef979538-8321-151a-dceb-9b0a7f7c7641/source/100x100bb.jpg
Current solutions do not solve my problem. I also tried:
try UIImage(data: Data(contentsOf: URL(string: artworkURL)!))
and
try UIImage(data: Data(contentsOf: (URL : artworkURL)))
and (fuller code) now using a static url to debug
let artworkString = "http://is1.mzstatic.com/image/thumb/Music/v4/ef/97/95/ef979538-8321-151a-dceb-9b0a7f7c7641/source/100x100bb.jpg" // album.artworkURL[index.row]
let url = URL(string: artworkString)
do {
mainImageView.image = try UIImage(data: Data(contentsOf: url!))
} catch _ {
print("No album artwork!")
}
This last one outputs "No album artwork!"!

You can user this library:
https://github.com/onevcat/Kingfisher
Kingfisher is a lightweight, pure-Swift library for downloading and caching images from the web. This project is heavily inspired by the popular SDWebImage. It provides you a chance to use a pure-Swift alternative in your next app.
let imagePath = URL(string: "url_of_your_image")
imageView.kf_setImageWithURL(NSURL(string: imagePath)!, placeholderImage: UIImage(named: "placeholder"))
you can also add placeholder image.

Related

CIImage contentsOfUrl Failed to convert UIImage to PNG

I have a Swift 4.1 (Xcode 9.3) Playground with these contents, and it's failing in a non-obvious way.
import UIKit
let url: URL = URL(string: "https://placekitten.com/500/500")!
let image: CIImage = CIImage(contentsOf: url)!
The resulting error is Failed to convert UIImage to PNG. For completeness, the returned place kitten is a JPG image.
Whereas I cannot tell you the reason, for why your code does not work as expected, you can use the following workaround to retrieve a CIImage located at a specific URL as suggested in the comments:
import UIKit
let url: URL = URL(string: "https://placekitten.com/500/500")!
let image = UIImage.init(data: try! Data.init(contentsOf: url))!
let convertedImage = CIImage.init(image: image)
Don't forget to add adequate error handling. I left that out for the sake of simplicity

Showing image from URL in iOS app [duplicate]

This question already has answers here:
Loading/Downloading image from URL on Swift
(39 answers)
Closed 5 years ago.
EDIT 3: Please also read my comment in the "answered" tagged answer. I think I won't use my synchronous method but change to the suggested asynchronous methods that were also given!
Ok I am struggling with some basic concepts of showing images from an URL from the internet on my app.
I use this code to show my image on an UIIamgeView in my ViewController:
func showImage() {
let myUrlImage = URL(string: linkToTheImage)
let image = try? Data(contentsOf: myUrlImage!)
imageView1.image = UIImage(data: image!)
}
Now basically I have the following question:
Is the whole image downloaded in this process?
Or works the UIImageView like a "browser" in this case and doesn't download the whole picture but only "positions" the image from the URL into my UIImageView?
EDIT:
The reason I asked is, I am basically doing a quiz app and all I need in the view is an image from a URL for each question - so it's no difference if I do it asynchronous or synchronous because the user has to wait for the image anyways. I am more interested in how do I get the fastest result:
So I wanted to know if my code really downloads the picture as a whole from the URL or just "Positions" it into the UIImageView?
If in my code the picture is downloaded in its full resolution anyways, then you are right, I could download 10 pictures asynchronously when the player starts the quiz, so he hopefully doesn't have to wait after each answer as long as he would wait when I start downloading synchronously after each answer.
Edit 2:
Because my Question was tagged as similar to another some more explanation:
I already read about synchronous and asynchronous downloads, and I am aware of the downsides of synchronous loading.
I am more interested in a really basic question, and I get the feeling I had one basic thing really wrong:
My initial thought was that if I open a link in my browser, for example this one,
https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/68dd54ca-60cf-4ef7-898b-26d7cbe48ec7/10-dithering-opt.jpg
the browser doesn't download the whole picture. But I guess this isn't the case? The whole picture is downloaded?
Never use Data(contentsOf:) to display data from a remote URL. That initializer of Data is synchronous and is only meant to load local URLs into your app, not remote ones. Use URLSession.dataTask to download image data, just as you would with any other network request.
You can use below code to download an image from a remote URL asynchronously.
extension UIImage {
static func downloadFromRemoteURL(_ url: URL, completion: #escaping (UIImage?,Error?)->()) {
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil, let image = UIImage(data: data) else {
DispatchQueue.main.async{
completion(nil,error)
}
return
}
DispatchQueue.main.async() {
completion(image,nil)
}
}.resume()
}
}
Display the image in a UIImageView:
UIImage.downloadFromRemoteURL(yourURL, completion: { image, error in
guard let image = image, error == nil else { print(error);return }
imageView1.image = image
})
You can do it this way. But in most cases it is better to download the image first by yourself and handle the displaying then (this is more or less what the OS is doing in the background). Also this method is more fail proof and allows you to respond to errors.
extension FileManager {
open func secureCopyItem(at srcURL: URL, to dstURL: URL) -> Bool {
do {
if FileManager.default.fileExists(atPath: dstURL.path) {
try FileManager.default.removeItem(at: dstURL)
}
try FileManager.default.copyItem(at: srcURL, to: dstURL)
} catch (let error) {
print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
return false
}
return true
}
}
func download() {
let storagePathUrl = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("image.jpg")
let imageUrl = "https://www.server.com/image.jpg"
let urlRequest = URLRequest(url: URL(string: imageUrl)!)
let task = URLSession.shared.downloadTask(with: urlRequest) { tempLocalUrl, response, error in
guard error == nil, let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print("error")
return
}
guard FileManager.default.secureCopyItem(at: tempLocalUrl!, to: storagePathUrl) else {
print("error")
return
}
}
task.resume()
}

Alamofire: Image download request issue

I'm new in the Swift, I am using Alamofire framework in my project, I am facing the following issue while giving the request for download image, I am using following code:
let imageURL = Constant.BaseAPI_URL + "/" + driver.driverProfile
Alamofire.request(.GET, imageURL).response() {
(_, _, data, _) in
let image = UIImage(data: data! as! NSData)
deiverProfileImageView.image = image
}
Issue :
Click Here For Image Description
Try this:
let imageURL = Constant.BaseAPI_URL + "/" + driver.driverProfile
Alamofire.download(imageURL).responseData { response in
if let data = response.result.value {
let image = UIImage(data: data)
deiverProfileImageView.image = image
}
}
Try below code
let imageURL = Constant.BaseAPI_URL + "/" + driver.driverProfile
Alamofire.request(imageURL).responseData(completionHandler: { response in
if let imageData = response.data
{
deiverProfileImageView.image = imageData
}
})
Try this:
let imageUrl = "www.your_url.com"
Alamofire.download(imageUrl).responseData {
response in
if let data = response.result.value {
let image = UIImage(data: data)
ProfileImage.image = image
}
}
or
The easiest way according to me will be using SDWebImage
Add this to your pod file
pod 'SDWebImage', '~> 4.0'
Run pod install
Now import SDWebImage
import SDWebImage
Now for setting image from url
imageView.sd_setImage(with: URL(string: "http://www.domain/path/to/image.jpg"), placeholderImage: UIImage(named: "placeholder.png"))
It will show placeholder image but when image is downloaded it will show the image from url .Your app will never crash
This are the main feature of SDWebImage
Categories for UIImageView, UIButton, MKAnnotationView adding web image and cache management
An asynchronous image downloader
An asynchronous memory + disk image caching with automatic cache expiration handling
A background image decompression
A guarantee that the same URL won't be downloaded several times
A guarantee that bogus URLs won't be retried again and again
A guarantee that main thread will never be blocked
Performances!
Use GCD and ARC
To know more https://github.com/rs/SDWebImage

Firebase - downloading few files

Is there a way to download couple of files (images) using Firebase Storage SDK and live cache those files, so after an image is downloaded the cache is updated?
Can I also observe in another view controller for this cache being updated?
I don't need a whole answer, just maybe a hint where to learn it. I've search through firebase documentation, found some info but I have absolutely no idea how to use it.
Take a look at NSURLCache. Basically what you'll do is, every time you upload a file to Firebase Storage, you can get a download URL and download it, then storeCachedResponse:forRequest: in the URL cache. Since this cache is shared, you can even grab it across activities.
Similarly, on download, you'll want to check for the cached request via cachedResponseForRequest: and if it doesn't exist, perform the download (at which point you cache the request for later).
Long term, we're hoping to enable this behavior for you out of the box, but for now, you can use NSURLCache to make it happen :)
I still haven't found a way to do this from within the Firebase Storage SDK. Here is some code I got off bhlvoong tutorials to cache images using NSCache.
import UIKit
let imageCache = NSCache<AnyObject, AnyObject>()
extension UIImageView {
func loadImageUsingCacheWithUrlString(urlString: String) {
self.image = nil
//check cache for image first
if let cachedImage = imageCache.object(forKey: urlString as NSString) as? UIImage {
self.image = cachedImage
return
}
//otherwise fire off a new download
let url = NSURL(string: urlString)
URLSession.shared.dataTask(with: url as! URL, completionHandler: { (data, response, error) in
//download hit an error so lets return out
if error != nil {
print(error)
return
}
DispatchQueue.main.async {
if let downloadedImage = UIImage(data: data!) {
imageCache.setObject(downloadedImage, forKey: urlString as NSString)
self.image = downloadedImage
}
}
}).resume()
}
}

Grab image from server in ios

I've seen that you can download an image in IOS through a URL. However, this requires that the URL be public. I'd much rather do it in such a way where my application makes a request to the server and if the necessary requirements are met, the server responds with an image. I do not want my images to be visible from the web.
The easiest option is to put the password in the URL:
let url = NSURL(string: "http://exapmle.com/2XwLZAgAO2VP9JqXg1s73zmB/foo.png")
let dataOptional: NSData? = NSData(contentsOfURL: url)
if let data = dataOptional {
let image = UIImage(data: data)
} else {
println("Error loading \(url)")
}

Resources