Loading/Downloading image from URL on Swift
Xcode 8 or later • Swift 3 or later
Synchronously:
if let filePath = Bundle.main.path(forResource: "imageName", ofType: "jpg"), let image = UIImage(contentsOfFile: filePath) {
imageView.contentMode = .scaleAspectFit
imageView.image = image
}
Asynchronously:
Create a method with a completion handler to get the image data from your url
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
Create a method to download the image (start the task)
func downloadImage(from url: URL) {
print("Download Started")
getData(from: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
// always update the UI from the main thread
DispatchQueue.main.async() { [weak self] in
self?.imageView.image = UIImage(data: data)
}
}
}
Usage:
override func viewDidLoad() {
super.viewDidLoad()
print("Begin of code")
let url = URL(string: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")!
downloadImage(from: url)
print("End of code. The image will continue downloading in the background and it will be loaded when it ends.")
}
Extension:
extension UIImageView {
func downloaded(from url: URL, contentMode mode: ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
Usage:
imageView.downloaded(from: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")
How to display Image from a url in SwiftUI
iOS 15 update:
you can use asyncImage in this way:AsyncImage(url: URL(string: "https://your_image_url_address"))
more info on Apple developers document:
AsyncImage
Using ObservableObject (Before iOS 15)
first you need to fetch image from url :
class ImageLoader: ObservableObject {
var didChange = PassthroughSubject<Data, Never>()
var data = Data() {
didSet {
didChange.send(data)
}
}
init(urlString:String) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
self.data = data
}
}
task.resume()
}
}
you can put this as a part of your Webservice class function too.
then in your ContentView struct you can set @State image in this way :
struct ImageView: View {
@ObservedObject var imageLoader:ImageLoader
@State var image:UIImage = UIImage()
init(withURL url:String) {
imageLoader = ImageLoader(urlString:url)
}
var body: some View {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width:100, height:100)
.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
}
}
}
Also, this tutorial is a good reference if you need more
Swift: Display Image from URL
There's a few things with your code as it stands:
- You are using a lot of casting, which is not needed.
- You are treating your URL as a local file URL, which is not the case.
- You are never downloading the URL to be used by your image.
The first thing we are going to do is to declare your variable as let
, as we are not going to modify it later.
let catPictureURL = URL(string: "http://i.imgur.com/w5rkSIj.jpg")! // We can force unwrap because we are 100% certain the constructor will not return nil in this case.
Then we need to download the contents of that URL. We can do this with the URLSession
object. When the completion handler is called, we will have a UIImage
downloaded from the web.
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
let image = UIImage(data: imageData)
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
Finally you need to call resume
on the download task, otherwise your task will never start:
downloadPicTask.resume()
.
All this code may look a bit intimidating at first, but the URLSession
APIs are block based so they can work asynchronously - If you block your UI thread for a few seconds, the OS will kill your app.
Your full code should look like this:
let catPictureURL = URL(string: "http://i.imgur.com/w5rkSIj.jpg")!
// Creating a session object with the default configuration.
// You can read more about it here https://developer.apple.com/reference/foundation/urlsessionconfiguration
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: catPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
print("Downloaded cat picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
let image = UIImage(data: imageData)
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
Display image from URL, Swift 4.2
First of all I'm pretty sure that in half a year you will find Objective-C very complicated and difficult. /p>
Second of all even your ObjC code is discouraged. Don't load data from a remote URL with synchronous Data(contentsOf
method. Regardless of the language use an asynchronous way like (NS)URLSession
.
And don't use Foundation collection types NSArray
and NSDictionary
in Swift. Basically don't use NS...
classes at all if there is a native Swift counterpart.
In Swift 4 you can easily decode the JSON with the Decodable
protocol directly into a (Swift) struct,
the URL string can be even decoded as URL
.
Create a struct
struct Item: Decodable {
// let copyright, date, explanation: String
// let hdurl: String
// let mediaType, serviceVersion, title: String
let url: URL
}
Uncomment the lines if you need more than the URL.
And load the data with two data tasks.
let url = URL(string: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY")!
let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
if let error = error { print(error); return }
do {
let decoder = JSONDecoder()
// this line is only needed if all JSON keys are decoded
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode(Item.self, from: data!)
let imageTask = URLSession.shared.dataTask(with: result.url) { (imageData, _, imageError) in
if let imageError = imageError { print(imageError); return }
DispatchQueue.main.async {
let apodImage = UIImage(data: imageData!)
let apodView = UIImageView(image: apodImage)
// do something with the image view
}
}
imageTask.resume()
} catch { print(error) }
}
task.resume()
Swift: Display image by URL saved in Firebase
As a suggestion you should avoid force unwrap and use Swift types, for example Data instead of NSData :) then, the code you tried works synchronously and it’s better to download your images asynchronously to avoid blocking the UI, try using URLSession, you can create a UIImageView extension, for example:
extension UIImageView {
func setImage(from urlAddress: String?) {
guard let urlAddress = urlAddress, let url = URL(string: urlAddress) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
DispatchQueue.main.async {
self.image = UIImage(data: data)
}
}
task.resume()
}
}
Then you can call it in this way:
cell.imageView.setImage(from: storeUrl)
Cannot display image from URL
The problem is that https://imgur.com/2yO5RbG is not an image; it is an html page, as your own test tells you right in the console. So the call to UIImage(data:)
fails and returns nil
. The image is at https://i.imgur.com/2yO5RbG.jpg.
How to display image from known image path - SwiftUI
You say NSOpenPanel
, so I'm making going to make the assumption here that we don't need to worry about waiting to load the image over a network:
if let nsImage = NSImage(contentsOf: url) {
Image(nsImage: nsImage)
}
Related Topics
Swift Xcode Index Freezing or Slow
Swift - How to Mutate a Struct Object When Iterating Over It
App Tracking Transparency Dialog Does Not Appear on iOS
What Are the Differences Between Throws and Rethrows in Swift
Swift - Unit Testing Private Variables and Methods
Sort Array by Calculated Distance in Swift
Swiftui: Can't Get the Transition of a Detailview to a Zstack in the Mainview to Work
Transparent Background for Texteditor in Swiftui
Swift: Testing Against Optional Value in Switch Case
What Does the Swiftui '@State' Keyword Do
Swiftui - Is There a Popviewcontroller Equivalent in Swiftui
Swift - Custom Setter on Property
Function with Datatask Returning a Value
Why Use Required Initializers in Swift Classes
How to Create Dictionary That Can Hold Anything in Key? or All the Possible Type It Capable to Hold
Concatenate Two Audio Files in Swift and Play Them
Split a String Without Removing the Delimiter in Swift
Swift Date(Byadding:To:) Returns Nil for Trivial Calculation in Repl