A comprehensive solution for displaying lazily loaded images on Apple platforms.
The library provides two components:
LazyImage
for SwiftUILazyImageView
for UIKit and AppKit
Both views have equivalent APIs.
It uses Nuke for loading images and has many customization options. It also supports GIF rendering thanks to Gifu. But GIF is not the most efficient format, so NukeUI also supports playing short videos out of the box.
WARNING. It's work-in-progress. Feel free to try it at your own risk by installing the package from the
main
branch.
The view is instantiated with a source.
struct ContainerView: View {
var body: some View {
LazyImage(source: "https://example.com/image.jpeg")
}
}
The view is called "lazy" because it loads the image from the source only when it appears on the screen. And when it disappears (or is deallocated), the current request automatically gets canceled. When the view reappears, the download picks up where it left off, thanks to resumable downloads.
The source can be anything from a String
to a full ImageRequest
.
LazyImage(source: "https://example.com/image.jpeg")
LazyImage(source: URL(string: "https://example.com/image.jpeg"))
LazyImage(source: URLRequest(url: URL(string: "https://example.com/image.jpeg")!))
let request = ImageRequest(
url: URL(string: "https://example.com/image.jpeg"),
processors: [ImageProcessors.Resize(width: 44)]
)
LazyImage(source: request)
Learn more about customizing image requests in "Image Requests."
LazyImage
is highly customizable. For example, it allows you to display a placeholder while the image is loading and display a custom view on failure.
LazyImage(source: "https://example.com/image.jpeg")
.placeholder {
Circle()
.foregroundColor(.blue)
.frame(width: 30, height: 30)
}
.failure { Image("empty") }
}
The image view is lazy and doesn't know the size of the image before it downloads it. Thus, you must specify the view size before loading the image. By default, the image will resize preserving the aspect ratio to fill the available space. You can change this behavior by passing a different content mode.
LazyImage(source: "https://example.com/image.jpeg")
.contentMode(.center) // .aspectFit, .aspectFill, .center, .fill
When the image is loaded, you can add an optional transition.
LazyImage(source: "https://example.com/image.jpeg")
.transition(.fadeIn(duration: 0.33))
You can pass a complete ImageRequest
as a source, but you can also configure the download via convenience modifiers.
LazyImage(source: "https://example.com/image.jpeg")
.processors([ImageProcessors.Resize(width: 44])
.priority(.high)
.pipeline(customPipeline)
You can also monitor the status of the download.
LazyImage(source: "https://example.com/image.jpeg")
.onStart { print("Task started \($0)")
.onProgress { ... }
.onSuccess { ... }
.onFailure { ... }
.onCompletion { ... }
And if some API isn't exposed yet, you can always access the underlying LazyImageView
instance. For example, you are currently going to need to access the underlying view to enable experimental video playback support:
LazyImage(source: "https://example.com/image.jpeg")
.onCreated { view in
view.isExperimentalVideoSupportEnabled = true
}
LazyImageView
is a LazyImage
counterpart for UIKit and AppKit with the equivalent set of APIs.
let imageView = LazyImageView()
imageView.placeholderView = UIActivityIndicatorView()
imageView.priority = .high
imageView.pipeline = customPipeline
imageView.onCompletion = { print("Request completed")
imageView.source = "https://example.com/image.jpeg"
- GIF support is currently limited to iOS and tvOS
- The support for watchOS is there but is currently limited
- Video playback currently requires a temporary disk storage
NukeUI | Swift | Xcode | Platforms |
---|---|---|---|
main branch | Swift 5.3 | Xcode 12.0 | iOS 11.0 / watchOS 5.0 / macOS 10.13 / tvOS 11.0 |
LazyImage
is available on the following platforms: iOS 13.0 / watchOS 7.0 / macOS 10.15 / tvOS 13.0
NukeUI is available under the MIT license. See the LICENSE file for more info.