So I'm trying to create a content feed using data fetched from my Node JS server.
Here I fetch data from my API
class Webservice { func getAllPosts(completion: @escaping ([Post]) -> ()) { guard let url = URL(string: "http://localhost:8000/albums") else { fatalError("URL is not correct!") } URLSession.shared.dataTask(with: url) { data, _, _ in let posts = try! JSONDecoder().decode([Post].self, from: data!); DispatchQueue.main.async { completion(posts) } }.resume() } }
Set the variables to the data fetched from the API
final class PostListViewModel: ObservableObject { init() { fetchPosts() } @Published var posts = [Post]() private func fetchPosts() { Webservice().getAllPosts { self.posts = $0 } } }
struct Post: Codable, Hashable, Identifiable { let id: String let title: String let path: String let description: String }
SwiftUI
struct ContentView: View { @ObservedObject var model = PostListViewModel() var body: some View { List(model.posts) { post in HStack { Text(post.title) Image("http://localhost:8000/" + post.path) Text(post.description) } } } }
The Text from post.title
and post.description
are display correctly but nothing displays from Image()
. How can I use a URL from my server to display with my image?
You can display an image in a SwiftUI view by using the Image view. First you need to add the image to a new image set in your Assets. xcassets file in the Xcode project navigator.
SwiftUI's views don't have a built-in function to render a view as an image, but we can write one ourselves in very little time. The key here is to wrap the view using UIHostingController , then render its view hierarchy into a UIGraphicsImageRenderer .
AsyncImage(url: URL(string: "https://your_image_url_address"))
more info on Apple developers document: AsyncImage
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With