A full-screen photo gallery for iOS, written in SwiftUI. It supports paging, pinch and double-tap zoom, a hero transition from the tapped image, drag-to-dismiss, a share/save sheet on long press, an optional author overlay, and paginated loading of more photos.
Requires iOS 18 and Swift 6.1. Distributed through Swift Package Manager only.
Add the package in Xcode (File → Add Package Dependencies) with the URL https://github.com/hole19/media-viewer, or in Package.swift:
.package(url: "https://github.com/hole19/media-viewer", from: "27.0.0")then depend on the H19MediaViewer product.
import H19MediaViewer
let items = urls.map { url in
MediaGalleryItem(
id: url.absoluteString,
source: .url(url),
author: MediaGalleryAuthor(avatarURL: avatarURL, name: "Alex", date: .now)
)
}
let gallery = MediaGalleryComposer.compose(
items: items,
initialIndex: tappedIndex,
sourceImageView: tappedImageView,
delegate: self,
configuration: MediaGalleryConfiguration(closeAccessibilityLabel: String(localized: "Close"))
)
present(gallery, animated: true)compose returns a UINavigationController configured for full-screen presentation with the custom transition. Present it from any view controller.
MediaGalleryItem.source is either .url(URL) (loaded with MediaGalleryImageLoader, or a loader you pass as loadImage:) or .image(UIImage). author is optional; when set, a blurred bar with the name and date shows at the bottom.
Every method of MediaGalleryDelegate has a default implementation, so implement only what you need:
| Method | Purpose |
|---|---|
mediaGallery(sourceImageViewFor:) |
The image view to animate to when dismissing, so the transition lands on the right thumbnail after the user paged |
mediaGallery(didShowItemAt:) |
Called when the visible page changes, e.g. to scroll the screen underneath |
mediaGalleryHasMoreItems |
Whether more items can be loaded |
mediaGalleryLoadMoreItems() |
Returns the next batch; called when the user nears the last page |
The gallery lays out from its container, not the screen, so it follows rotation, split view and window resizes.
The package ships no strings. Pass the localized close label through MediaGalleryConfiguration. Accessibility identifiers are exposed as MediaGalleryAccessibilityID for UI tests.
swift package resolve
xcodebuild -scheme H19MediaViewer -destination 'platform=iOS Simulator,name=iPhone 16' test
SwiftUI previews live next to the views.
Sandbox/ is a small app for trying the gallery by hand: a thumbnail grid with the hero transition, drag-to-dismiss, paginated loading and an author overlay toggle. It is not part of the package, so consumers and xcodebuild -scheme H19MediaViewer never build it.
The repo stays SPM-only, so the Xcode project is generated with XcodeGen (brew install xcodegen) and git-ignored:
cd Sandbox
xcodegen generate
open Sandbox.xcodeproj
Run the Sandbox scheme on a simulator, or from the command line:
xcodebuild -project Sandbox.xcodeproj -scheme Sandbox -destination 'platform=iOS Simulator,name=iPhone 16' build
Re-run xcodegen generate after changing Sandbox/project.yml or adding files.
MIT, see LICENSE.