Json : https://picsum.photos/v2/list
ContentView.swift
// // ContentView.swift // Swiftuitest // // Created by Cairocoders // import SwiftUI struct ContentView: View { @ObservedObject var items = Remote(url: URL(string: "https://picsum.photos/v2/list")!, transform: { try? JSONDecoder().decode([Photo].self, from: $0) }) var body: some View { NavigationView { if items.value == nil { ProgressView() .onAppear { items.load() } }else { List { ForEach(items.value!) { photo in NavigationLink( destination: PhotoView(photo.download_url), label: { Text(photo.author) }) } }.navigationTitle("Authors") } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }Model.swift
// // Model.swift // Swiftuitest // // Created by Cairocoders // import Foundation struct Photo: Codable, Identifiable { let id: String let author: String let width, height: Int let url, download_url: URL } struct PhotoLoadingError: Error {} //View Model final class Remote<Asc>: ObservableObject { @Published var result: Result<Asc, Error>? = nil var value: Asc? { try? result?.get()} let url:URL let transform: (Data) ->Asc? init(url: URL, transform: @escaping (Data) ->Asc?) { self.url = url self.transform = transform } func load() { URLSession.shared.dataTask(with: url) { (data, _, _) in DispatchQueue.main.async { if let d = data, let v = self.transform(d) { self.result = .success(v) } else { self.result = .failure(PhotoLoadingError()) } } }.resume() } }PhotoView.swift
// // PhotoView.swift // Swiftuitest // // Created by Cairocoders // import SwiftUI struct PhotoView: View { @ObservedObject var image: Remote<UIImage> init(_ url: URL) { self.image = Remote(url: url, transform: { UIImage(data: $0) }) } var body: some View { Group { if image.value == nil { ProgressView() .onAppear { image.load() } } else { Image(uiImage: image.value!) .resizable() .aspectRatio(contentMode: .fit) } } } }