Last active
June 22, 2024 02:13
-
-
Save moto0000/b79cc9782618210824acb545dd31cb91 to your computer and use it in GitHub Desktop.
Mockable SwiftUI.AsyncImage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
public struct AsyncImage<Content>: View where Content: View { | |
private var content: (ImageProvider) -> _ConditionalContent< | |
SwiftUI.AsyncImage<Content>, Content | |
> | |
@Environment(\.imageProvider) var imageProvider | |
public init( | |
url: URL?, | |
scale: CGFloat = 1 | |
) where Content == Image { | |
self.content = { imageProvider in | |
if let uiImage = url.flatMap(imageProvider) { | |
return ViewBuilder.buildEither( | |
second: Image(uiImage: uiImage) | |
) | |
} else { | |
return ViewBuilder.buildEither( | |
first: SwiftUI.AsyncImage( | |
url: url, | |
scale: scale | |
) | |
) | |
} | |
} | |
} | |
public init<I, P>( | |
url: URL?, | |
scale: CGFloat = 1, | |
@ViewBuilder content: @escaping (Image) -> I, | |
@ViewBuilder placeholder: @escaping () -> P | |
) where Content == _ConditionalContent<I, P>, I: View, P: View { | |
self.content = { imageProvider in | |
if let uiImage = url.flatMap(imageProvider) { | |
return ViewBuilder.buildEither( | |
second: ViewBuilder.buildEither( | |
first: content(Image(uiImage: uiImage)) | |
) | |
) | |
} else { | |
return ViewBuilder.buildEither( | |
first: SwiftUI.AsyncImage( | |
url: url, | |
scale: scale, | |
content: content, | |
placeholder: placeholder | |
) | |
) | |
} | |
} | |
} | |
public init( | |
url: URL?, | |
scale: CGFloat = 1, | |
transaction: Transaction = Transaction(), | |
@ViewBuilder content: @escaping (AsyncImagePhase) -> Content | |
) { | |
self.content = { imageProvider in | |
if let uiImage = url.flatMap(imageProvider) { | |
return ViewBuilder.buildEither( | |
second: content(.success(Image(uiImage: uiImage))) | |
) | |
} else { | |
return ViewBuilder.buildEither( | |
first: SwiftUI.AsyncImage( | |
url: url, | |
scale: scale, | |
transaction: transaction, | |
content: content | |
) | |
) | |
} | |
} | |
} | |
public var body: some View { | |
self.content(self.imageProvider) | |
} | |
} | |
public typealias ImageProvider = (URL) -> UIImage? | |
private struct Key: EnvironmentKey { | |
static var defaultValue: ImageProvider = { _ in nil } | |
} | |
extension EnvironmentValues { | |
public var imageProvider: ImageProvider { | |
get { self[Key.self] } | |
set { self[Key.self] = newValue } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment