Skip to content

docs(screen-orientation): fix iOS orientation snippet for UIScene - #2597

Open
aihdene-genetec wants to merge 2 commits into
ionic-team:mainfrom
aihdene-genetec:docs/screen-orientation-uiscene
Open

aihdene-genetec wants to merge 2 commits into
ionic-team:mainfrom
aihdene-genetec:docs/screen-orientation-uiscene

Conversation

@aihdene-genetec

Copy link
Copy Markdown

The supportedInterfaceOrientationsFor override documented in the iOS section reads the root view controller from self.window:

return UIInterfaceOrientationMask(rawValue: (self.window!.rootViewController as! CAPBridgeViewController).supportedInterfaceOrientations.rawValue)

Capacitor 8.5 adopted the UIScene lifecycle, where the window is created and owned by SceneDelegate:

window = UIWindow(windowScene: windowScene)
window?.rootViewController = CAPBridgeViewController()

AppDelegate.window is therefore always nil, so the force unwrap traps the moment UIKit queries the orientation mask — which happens during window?.makeKeyAndVisible(), before the app ever renders. Following the docs as written on 8.5+ gives a crash on every launch:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)

0  libswiftCore.dylib  _assertionFailure(_:_:file:line:flags:)
2  App.debug.dylib     AppDelegate.application(_:supportedInterfaceOrientationsFor:) (AppDelegate.swift:51)
3  UIKitCore           _UISafelyGetOrientationMask
4  UIKitCore           -[UIApplication _supportedInterfaceOrientationsForWindow:]
...
13 UIKitCore           -[UIWindow _mainQueue_makeKeyAndVisible]
14 App.debug.dylib     SceneDelegate.scene(_:willConnectTo:options:) (SceneDelegate.swift:20)

Changes

  • Read the root view controller from the window passed into the method. UIKit supplies this under both lifecycles, so the snippet works before and after 8.5 without branching on version.
  • Use a conditional cast instead of as!, returning .all when the root view controller isn't a CAPBridgeViewController. .all imposes no app-level restriction, so the view controller and Info.plist still govern, matching the previous effective behavior when the bridge controller is present.
  • Add a note with a before/after diff, since apps that already copied the old snippet need to change it to launch on 8.5+.

Docs-only; no plugin source is touched. The edit is outside the <docgen-*> markers, so docgen won't overwrite it, and markdown isn't part of the package's prettier glob (**/*.{css,html,ts,js,java}).

Testing

Verified on a Capacitor 8.5.2 app (Xcode 27.0, iPad A16 simulator, iOS 27.0): the documented snippet crashes on launch as above, and the updated snippet launches and stays running, with orientation locking still applied to presented view controllers.

aihdene-genetec and others added 2 commits September 16, 2026 14:47
The documented `supportedInterfaceOrientationsFor` override reads the
root view controller from `self.window`. Capacitor 8.5 adopted the
UIScene lifecycle, where the window is created and owned by
`SceneDelegate`, so `self.window` on the `AppDelegate` is always nil and
the force unwrap traps on launch.

Read the root view controller from the `window` passed into the method,
which UIKit supplies under both lifecycles, and use a conditional cast so
a non-bridge root view controller returns `.all` rather than crashing.
Also add a note with a before/after diff for apps that already copied the
previous snippet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant