How to Display an Image by an API Url? Swift

How can I display an image by an API URL? Swift

Use a loader like this to load the data:

import Combine

public class DataLoader: ObservableObject {

public let objectWillChange = PassthroughSubject<Data,Never>()

public private(set) var data = Data() {
willSet {
objectWillChange.send(newValue)
}
}

private let resourseURL: URL?

public init(resourseURL: URL?){
self.resourseURL = resourseURL
}

public func loadImage() {
guard let url = resourseURL else {
return
}

URLSession.shared.dataTask(with: url) { (data,_,_) in
guard let data = data else {
return
}
DispatchQueue.main.async {
self.data = data
}
} .resume()
}
}

And a struct like this to display it:

import SwiftUI 

struct WebImage: View {

@ObservedObject private var imageLoader: DataLoader

public init(imageURL: URL?) {
imageLoader = DataLoader(resourseURL: imageURL)
}

public var body: some View {
if let uiImage = UIImage(data: self.imageLoader.data) {
return AnyView(Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: ContentMode.fit))
} else {
return AnyView(Image(systemName: "ellipsis")
.onAppear(perform: { self.imageLoader.loadImage() }))
}
}
}

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

Display image in tableview that are fetched in response of the api as a URL in swift

UIImage(named: String) tries to load the image locally,
You need to download the images.
For this purpose, consider using an image downloader like the kingfisher:

imageView.kf.setImage(with: url)

see more: https://github.com/onevcat/Kingfisher

Swift 3: How to display an image using URL with API

From apples docs:

Important

Do not use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.

Instead, for non-file URLs, consider using the dataTaskWithURL:completionHandler: method of the NSURLSession class. See URL Session Programming Guide for details.

Maybe consider using Alamofire for this task?

Alamofire.request(.GET, "http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg").response { (request, response, data, error) in
self.imageURL.image = UIImage(data: data, scale:1)
}

How to display image from API in swift?

You need to create an NSURLSession to get the NSData from your API. Then you can put that data into a UIImage and display it in a UIImageView.

Full Example:

@IBOutlet weak var testImageView: UIImageView!

let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
if let url = NSURL(string: "http://my_api/getUserImg"){

let task = session.dataTaskWithURL(url, completionHandler: {data, response, error in

if let err = error {
print("Error: \(err)")
return
}

if let http = response as? NSHTTPURLResponse {
if http.statusCode == 200 {
let downloadedImage = UIImage(data: data!)
dispatch_async(dispatch_get_main_queue(), {
self.testImageView.image = downloadedImage
})
}
}
})
task.resume()
}

Example Project on GitHub

Displaying the Image From API using DidSelectRow

You need to return UIImage :

class MoviePresenter: MoviePresenterProtocol {

...
// Convert data to UIImage
func getImageData(by row: Int) -> UIImage? {
return UIImage(data: cache[row])
}

You need yo use UIImage and UIImage view to configure cell :

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell

let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let image = presenter.getImageData(by: row)
// cell is now configured with an image
cell.configureCell(title: title, overview: overview, image: image)
return cell
}

You need to modify cell.configureCell to handle UIImage? instead of data.

When selecting a cell you must use UIImage to init VC :

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController

let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
dc.imagemovie = presenter.getImageData(by: row)// now an image

self.navigationController?.pushViewController(dc, animated: true)
}

Use UIImage to initialise image movie in detail vc :

class MovieDeatilsViewController: UIViewController {
@IBOutlet weak var movieImageView: UIImageView! // Image view here
@IBOutlet weak var movieTitle: UILabel!
@IBOutlet weak var movieOverview: UILabel!

var titlemovie = ""
var overview = ""
var imagemovie : UIImage?

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated: animated)

movieTitle.text = titlemovie
movieOverview.text = overview
// here you could also display a default image
// if image is not set
if let image = imagemovie {
movieImageView.image = image
}

}

}

Swift: Display Image from URL

There's a few things with your code as it stands:

  1. You are using a lot of casting, which is not needed.
  2. You are treating your URL as a local file URL, which is not the case.
  3. 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()


Related Topics



Leave a reply



Submit