Skip to content

Instantly share code, notes, and snippets.

@StarLard
Last active December 30, 2020 01:12
Show Gist options
  • Save StarLard/fb1e02f4dc616aee02970453847c1c2e to your computer and use it in GitHub Desktop.
Save StarLard/fb1e02f4dc616aee02970453847c1c2e to your computer and use it in GitHub Desktop.
FetchImageView
import SwiftUI
import Nuke
@available(watchOS 7.0, *)
@available(tvOS 14.0, *)
@available(iOS 14.0, *)
@available(OSX 11.0, *)
public struct FetchImageView<Placeholder>: View where Placeholder: View {
public var body: some View {
content
.onAppear {
if let request = self.request {
// Restarts the request if previous download failed
fetchImage.fetch(request: request, lowDataRequest: lowDataRequest)
} else {
fetchImage.reset()
}
fetchImage.priority = .normal
}
.onDisappear {
fetchImage.priority = .low
}
}
/// Initializes the fetch request and immediately start loading.
public init(request: ImageRequest? = nil, lowDataRequest: ImageRequest? = nil, @ViewBuilder placeholder: () -> Placeholder) {
self.placeholder = placeholder()
self.request = request
self.lowDataRequest = lowDataRequest
}
/// Initializes the fetch request and immediately start loading.
public init(url: URL, @ViewBuilder placeholder: () -> Placeholder) {
self.init(request: ImageRequest(url: url), placeholder: placeholder)
}
/// A convenience initializer that fetches the image with a regular URL with
/// constrained network access disabled, and if the download fails because of
/// the constrained network access, uses a low data URL instead.
public init(regularUrl: URL, lowDataUrl: URL, @ViewBuilder placeholder: () -> Placeholder) {
var request = URLRequest(url: regularUrl)
request.allowsConstrainedNetworkAccess = false
self.init(request: ImageRequest(urlRequest: request), lowDataRequest: ImageRequest(url: lowDataUrl), placeholder: placeholder)
}
@StateObject
private var fetchImage = FetchImage()
private var request: ImageRequest?
private var lowDataRequest: ImageRequest?
private var placeholder: Placeholder
@ViewBuilder
private var content: some View {
if let fetchedImage = fetchImage.image {
#if os(macOS)
Image(nsImage: fetchedImage)
#else
Image(uiImage: fetchedImage)
#endif
} else {
placeholder
}
}
}
@available(watchOS 7.0, *)
@available(tvOS 14.0, *)
@available(iOS 14.0, *)
@available(OSX 11.0, *)
public extension FetchImageView where Placeholder == Color {
/// Initializes the fetch request and immediately start loading.
init(request: ImageRequest? = nil, lowDataRequest: ImageRequest? = nil) {
self.init(request: request, lowDataRequest: lowDataRequest) {
Color.white
}
}
/// Initializes the fetch request and immediately start loading.
init(url: URL) {
self.init(url: url) {
Color.white
}
}
/// A convenience initializer that fetches the image with a regular URL with
/// constrained network access disabled, and if the download fails because of
/// the constrained network access, uses a low data URL instead.
init(regularUrl: URL, lowDataUrl: URL) {
self.init(regularUrl: regularUrl, lowDataUrl: lowDataUrl) {
Color.white
}
}
}
#if DEBUG
@available(watchOS 7.0, *)
@available(tvOS 14.0, *)
@available(iOS 14.0, *)
@available(OSX 11.0, *)
struct FetchImageView_Previews: PreviewProvider {
static var previews: some View {
FetchImageView(url: URL(string: "https://cloud.githubusercontent.com/assets/1567433/13918338/f8670eea-ef7f-11e5-814d-f15bdfd6b2c0.png")!) {
Text("Loading...")
}
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment