CustomImage
is a versatile SwiftUI abstraction that unifies static and remote image rendering into a single interface. It supports image tinting, custom placeholders, and fallback options — and leverages CachedAsyncImage for efficient remote image handling with memory and disk caching.
public enum CustomImage {
case app(image: Image, color: Color?)
case remote(url: URL?, imageColor: Color? = nil, placeholder: Image?, placeholderColor: Color? = nil)
case remoteIncludingRemotePlaceholder(
url: URL?,
imageColor: Color? = nil,
placeholderUrl: URL?,
placeholder: Image?,
placeholderColor: Color? = nil
)
}
public enum CustomImageRenderingMode {
case original
case template(color: Color? = nil)
}
.original
- renders the image as-is..template
- renders image as template with optional color tint.
func view(isResizable: Bool = true, mode: CustomImageRenderingMode = .original) -> some View
- Returns a SwiftUI View representation of the image.
- Automatically handles caching, placeholders, and rendering mode.
- Behavior adapts based on the enum case and image availability.
Outside of UI components, prefer using native Image
for static assets — unless you're displaying a .remote
or .remoteIncludingRemotePlaceholder
.
In those cases, CustomImage
is necessary to handle loading, caching, and fallback logic properly.
// Used inside a component – recommended:
CustomButton(
theme: .light,
style: .solidPrimary,
size: .normal,
icon: .app(image: Image("icon-starsharp-solid"), color: nil),
title: "Ok",
action: {
storeOpened = true
},
fullWidth: true,
badge: false
)
.disabled(storeOpened)
// Used for remote image loading – also recommended:
CustomImage.remote(
url: URL(string: "https://example.com/image.png"),
imageColor: .blue,
placeholder: Image(systemName: "photo"),
placeholderColor: .gray
).view()
// Overkill:
CustomImage.app(image: Image("logo"), color: .primary500)
.view()
.scaledToFit()
.frame(width: 24, height: 24)
// Prefer:
Image("logo")
.renderingMode(.template)
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
.foregroundColor(.primary500)
When .remote
or .remoteIncludingRemotePlaceholder
is used, CachedAsyncImage
handles loading, caching, and fallback logic.
If the main URL is missing or fails, fallback images (local or remote) are rendered.
Supports recursive placeholder fallback with nested CachedAsyncImage
usage.
// Overkill:
CustomImage.app(image: Image("star"), color: .yellow)
.view()
.scaledToFit()
.frame(width: 24, height: 24)
// Prefer:
Image("star")
.renderingMode(.template)
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
.foregroundColor(.yellow)
CustomImage.remote(
url: URL(string: "https://example.com/image.png"),
imageColor: .blue,
placeholder: Image(systemName: "photo"),
placeholderColor: .gray
).view()
CustomImage.remoteIncludingRemotePlaceholder(
url: URL(string: "https://example.com/image.png"),
imageColor: .blue,
placeholderUrl: URL(string: "https://example.com/placeholder.png"),
placeholder: nil,
placeholderColor: .gray
).view()
- 🔄 Uses
CachedAsyncImage
under the hood for all remote image handling - 🧱 Relies on SwiftUI's
Image
,Color
, and view builder APIs
See also: CachedAsyncImage