✨ A lightweight way to use the latest SwiftUI modifier APIs while gracefully supporting older iOS versions.
Every fall, a new version of iOS ships with shiny new SwiftUI APIs. However, a lot of apps will continue to support the last version of iOS (i.e., N-1). That often leads to code that looks like this:
if #available(iOS 26.0, *) {
SomeView().glassEffect()
} else {
SomeView()
}
Multiply that across your entire codebase, and suddenly you’re tangled in #available
checks and duplicated code.
This project offers a simple Backport
type that lets you use new SwiftUI APIs with a fallback — without cluttering your UI code.
- ✅ Write modern SwiftUI code that reads cleanly
- ✅ Seamlessly backport newer iOS modifiers to earlier versions
- ✅ No more nested
if #available
blocks - ✅ Just one Swift file — easy to drop in and maintain
It’s based on Dave DeLong’s elegant approach to backwards compatibility in Swift. Definitely read that before diving in.
Instead of writing:
if #available(iOS 26.0, *) {
MyView().glassEffect()
} else {
MyView()
}
You can write:
MyView()
.backport.glasseffect()
And the Backport
type handles the fallback internally. Since iOS version checks occur at compile time, you aren't hit with SwiftUI performance penalities from if/else
checks. Here, the left side is using a thin material, while the right uses a glass effect on iOS 26 and above:
You can add this repo as a dependency in Xcode:
- Open your project.
- Go to File > Add Packages…
- Enter the URL: https://github.com/superwall/iOS-Backports
- Choose the latest version and add it to your app target.
Then, import the package:
import Backport
struct MyView: View {
var body: some View {
AwesomeView()
.backport.glassEffect()
}
}
Just copy the Backport.swift
file into your project. That’s it.
iOS Version | Modifier | Description |
---|---|---|
iOS 18.0 | presentationSizeForm() |
Applies .presentationSizing(.form) |
iOS 18.0 | zoom(sourceID:in:) |
Applies a zoom navigation transition |
iOS 18.0 | matchedTransitionSource(id:in:) |
Marks a view as a matched transition source |
iOS 18.1 | imagePlayground(_:completion:) |
Presents an image playground sheet |
iOS 26.0 | glassEffect(_:in:isEnabled:) |
Applies a glass effect |
iOS 26.0 | glassEffect(_:in:isEnabled:fallback:) |
Glass effect with fallback for unsupported OS |
iOS 26.0 | glassButtonStyle() |
Applies the glass button style |
iOS 26.0 | glassEffectTransition(_:isEnabled:) |
Animates glass transitions |
iOS 26.0 | glassEffectID(_:in:) |
Tags glass views for matched animations |
iOS 26.0 | backgroundExtensionEffect() |
Extends background beyond safe areas |
iOS 26.0 | scrollEdgeEffectStyle(_:for:) |
Customizes scroll view edge effects |
iOS 26.0 | scrollEdgeEffectDisabled(_:for:) |
Disables scroll edge effects |
iOS 26.0 | symbolColorRenderingMode(_:) |
Sets symbol image rendering mode |
iOS 26.0 | symbolVariableValueMode(_:) |
Sets variable value rendering mode |
Got a new SwiftUI modifier you'd like to backport? Open a PR or file an issue — contributions are welcome!
MIT
Made with ❤️ by Superwall