A powerful SwiftUI library that solves one of the most frustrating limitations in SwiftUI: displaying overlays above modal presentations like sheets and full screen covers.
β Problem | β Solution |
---|---|
![]() |
![]() |
Standard SwiftUI doesn't provide a clean way to display UI elements above sheets and full screen covers.
When you present a modal view:
- Any overlays in the parent view become invisible
- ZStack with high z-index values doesn't help
- There's no built-in way to show global overlays above all view hierarchies
This limitation makes it impossible to create:
- Global toasts that stay visible during modal presentations
- Picture-in-picture videos that remain on screen regardless of navigation
- System-wide alerts that appear above all content
- Custom loading indicators that don't disappear during sheet transitions
Overlayer solves this problem by creating a separate UIWindow that exists above the entire app's view hierarchy.
This enables:
- Toast notifications that remain visible above sheets and full screen covers
- Draggable PiP video players that persist across view transitions
- Custom alerts that always appear on top
- Any overlay UI that needs to exist above all other content
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
OverlayerRootView {
ContentView()
}
}
}
}
Overlayer provides two main API styles:
struct ContentView: View {
@State private var showToast = false
var body: some View {
VStack {
Button("Show Toast") {
showToast = true
// Auto-dismiss after 2 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
showToast = false
}
}
}
.overlayer(isPresented: $showToast) {
ToastView(message: "This is a toast!")
}
}
}
struct ContentView: View {
@State private var selectedProduct: Product? = nil
var body: some View {
List(products) { product in
Button(product.name) {
selectedProduct = product
}
}
.overlayer(item: $selectedProduct) { product in
ProductDetailView(product: product, isPresented: $selectedProduct)
}
}
}
All overlays support standard SwiftUI transitions and animations:
.overlayer(isPresented: $showToast, animation: .spring) {
ToastView()
.transition(.move(edge: .top).combined(with: .opacity))
}
- iOS 17.0+
- Swift 5.9+
- Xcode 15.0+
Add the following to your Package.swift
file:
dependencies: [
.package(url: "https://github.com/tornikegomareli/Overlayer.git", from: "0.0.1")
]
Or add it directly through Xcode:
- Go to File > Swift Packages > Add Package Dependency
- Enter the repository URL:
https://github.com/tornikegomareli/Overlayer.git
- Specify the version constraints
- Click Next and then Finish
You can check OverlayerDemoPreview
for advanced and different type of examples including PiP and full screen cover.
Check OverlayerSolutionDemo
for basic solution demo.
Check StandardSwiftUILimitationDemo
for the core problem.
Overlayer uses a separate UIWindow instance to render overlays above the entire application:
OverlayerRootView
creates a manager and adds it to the SwiftUI environment- The manager creates a new UIWindow with a higher window level
- View modifiers communicate with the manager through the environment
- Overlays are rendered in the separate window, above all other content
This approach bypasses SwiftUI's view hierarchy limitations, allowing overlays to appear above everything.
Overlayer is available under the MIT license. See the LICENSE file for more info.
Created by Tornike
Any kind of contributions, finding bugs, improving API or feature ideas are kindly welcome π€