A Swift package that provides orientation locking capabilities for SwiftUI views.
SwiftUI doesn't have a built-in way to lock orientation for specific views. This package addresses this limitation by providing a centralized orientation manager and a view modifier to control orientations on a per-view basis.
- Lock orientation for specific SwiftUI views
- Support for all iOS orientations (portrait, landscape, upside down)
- Automatic resolution of conflicting orientation constraints
- Easy-to-use SwiftUI view modifier
- iOS 14.0 or later
- Swift 5.5 or later
- Xcode 13.0 or later
Add the following dependency to your Package.swift
file:
https://github.com/ivan-magda/swiftui-interface-orientation.git
dependencies: [
.package(url: "https://github.com/ivan-magda/swiftui-interface-orientation.git", from: "1.0.0")
]
Or add it directly through Xcode:
- In Xcode, select "File" → "Add Packages..."
- Enter the URL:
https://github.com/ivan-magda/swiftui-interface-orientation.git
- Choose the version rule (e.g., "Up to Next Major")
- Click "Add Package"
Configure the orientation manager early in your app lifecycle, typically in your App or Scene delegate:
import SwiftUIInterfaceOrientation
@main
struct MyApp: App {
init() {
// Configure with default orientations from Info.plist
InterfaceOrientationManager.configure()
// Or specify custom defaults
// InterfaceOrientationManager.configure(configuration: .init(defaultOrientations: .portrait))
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Apply the .supportedInterfaceOrientations()
modifier to any SwiftUI view:
import SwiftUI
import SwiftUIInterfaceOrientation
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink("Normal View") {
Text("This view uses the app's default orientations")
}
NavigationLink("Portrait Only") {
PortraitOnlyView()
}
NavigationLink("Landscape Only") {
LandscapeOnlyView()
}
}
}
}
}
struct PortraitOnlyView: View {
var body: some View {
Text("This view is locked to portrait orientation")
.supportedInterfaceOrientations(.portrait)
}
}
struct LandscapeOnlyView: View {
var body: some View {
Text("This view is locked to landscape orientation")
.supportedInterfaceOrientations([.landscapeLeft, .landscapeRight])
}
}
For complete integration, you need to implement either the UIApplicationDelegate
method or the UIWindowSceneDelegate
method (for iOS 13+) to handle orientation requests:
import UIKit
import SwiftUIInterfaceOrientation
class AppDelegate: UIResponder, UIApplicationDelegate {
// ... other AppDelegate code ...
func application(
_ application: UIApplication,
supportedInterfaceOrientationsFor window: UIWindow?
) -> UIInterfaceOrientationMask {
// Delegate to the orientation manager
return InterfaceOrientationManager.shared.supportedInterfaceOrientations
}
}
import UIKit
import SwiftUIInterfaceOrientation
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// ... other SceneDelegate code ...
func windowScene(_ windowScene: UIWindowScene,
didUpdate previousCoordinateSpace: UICoordinateSpace,
interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation,
traitCollection previousTraitCollection: UITraitCollection) {
// Let the manager know when orientation changes
InterfaceOrientationManager.shared.updateSupportedInterfaceOrientations()
}
func windowScene(_ windowScene: UIWindowScene,
supportedInterfaceOrientationsFor window: UIWindow) -> UIInterfaceOrientationMask {
// Delegate to the orientation manager
return InterfaceOrientationManager.shared.supportedInterfaceOrientations
}
}
import SwiftUI
import SwiftUIInterfaceOrientation
class OrientationDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
supportedInterfaceOrientationsFor window: UIWindow?
) -> UIInterfaceOrientationMask {
return InterfaceOrientationManager.shared.supportedInterfaceOrientations
}
}
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(OrientationDelegate.self) var delegate
init() {
InterfaceOrientationManager.configure()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
The package uses a centralized manager (InterfaceOrientationManager
) that keeps track of orientation constraints from active views. When views appear and disappear, they register and unregister their constraints with the manager.
The manager computes the intersection of all active constraints to determine which orientations should be allowed. If the intersection would be empty (meaning there are conflicting constraints), it falls back to the default orientations.
MIT License