The RemoteContentView
can download a remote content from a URL and display different loading states.
The package supports JSON and Plist (using Foundation Decodable
protocol), images, and custom types.
You must provide a view to display the result value, and optionally a view for each loading state.
Displaying the list of posts received from the JSONPlaceholder API. The Post
struct conforms to Codable
protocol used for JSON decoding.
struct Post : Codable {
var id: Int
var title: String
var body: String
}
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
let content = DecodableRemoteContent(url: url, type: [Post].self, decoder: JSONDecoder())
let view = RemoteContentView(remoteContent: content) { posts in
List(posts, id: \Post.id) { post in
VStack {
Text(post.title)
Text(post.body)
}
}
}
Note, if you use default JSON decoder you can omit the last parameter:
let content = DecodableRemoteContent(url: url, type: [Post].self)
let url = URL(string: "http://optipng.sourceforge.net/pngtech/img/lena.png")!
let remoteImage = RemoteImage(url: url)
let view = RemoteContentView(remoteContent: remoteImage) {
Image(uiImage: $0)
}
RemoteContentView
supports 4 customizable loading states:
let view = RemoteContentView(remoteContent: remoteContent,
empty: {
EmptyView()
},
progress: { progress in
Text("Loading in progress: \(progress)")
},
failure: { error, retry in
VStack {
Text(error)
Button("Retry", action: retry)
}
},
content: { posts in
List(posts, id: \Post.id) { post in
VStack {
Text(post.title)
Text(post.body)
}
}
})
The RemoteContent
protocol defines objects that provide content and manage loading state.
public protocol RemoteContent : ObservableObject {
associatedtype Value
associatedtype Progress
var loadingState: RemoteContentLoadingState<Value, Progress> { get }
func load()
func cancel()
}
The package provides two implementations:
DecodableRemoteContent
for a content, loaded from a URL, represented byDecodable
objects;RemoteImage
for images.
You can implement your own RemoteContent
object if you need custom loading or to make the view work with existing content providers. You can find an example in CustomRemoteContent.playground.