Skip to content

Adopt the UIScene lifecycle on tvOS - #719

Open
bartleman wants to merge 1 commit into
moonlight-stream:masterfrom
bartleman:tvos-uiscene-lifecycle
Open

bartleman wants to merge 1 commit into
moonlight-stream:masterfrom
bartleman:tvos-uiscene-lifecycle

Conversation

@bartleman

@bartleman bartleman commented Aug 16, 2026 •

Copy link
Copy Markdown

Problem

An app built against the tvOS 27 SDK that still uses the legacy UIApplicationMain + storyboard lifecycle fails to launch. The system refuses to create its scene and the app exits before main, with this in the device log:

Application failed to launch: UIScene life cycle is required for apps built with this SDK.
See "Transitioning to the UIKit scene-based life cycle" ...
[FBSceneManager] Scene creation failed: ... ("scene-creation-failed")

Apps built against the tvOS 26.5 SDK are exempt and still run on tvOS 27, so this only bites once you build the tvOS target with Xcode 27 / the tvOS 27 SDK.

Fix

  • Add a minimal UIApplicationSceneManifest to Moonlight TV/Info.plist.
  • Add a small UIWindowSceneDelegate that builds the window from the Main storyboard. To avoid adding a new source file to the project, it's declared in AppDelegate.m under #if TARGET_OS_TV.
  • Make the tvOS HDR / refresh-rate code scene-safe: under the scene lifecycle the app delegate's -window is nil, so updatePreferredDisplayMode: now reads the window from the view controller (self.view.window). If the view isn't attached to a window yet (the stream is started from viewDidLoad, so the HDR callback can arrive before the push animation completes), it falls back to the connected UIWindowScene's window.

Notes

  • tvOS only. Only the tvOS target is touched. The iOS target is unchanged; it will need the same migration when built against a future iOS SDK that enforces scenes (that's a larger change — SWRevealViewController, shortcut-item handling — so I've left it out of this PR).
  • Does not change TVOS_DEPLOYMENT_TARGET. UIScene has existed since tvOS 13, so nothing here needs more than the current tvOS 15 minimum.
  • Rebased onto current master (Xcode 27 project settings, GitHub Actions CI).

Testing

Built with Xcode 27 beta against the tvOS 27 SDK and run on an Apple TV 4K (3rd gen), tvOS 27.0 (24J5346a): the app launches, the UI appears, host discovery/pairing work, and streaming works. Also verified the tvOS 26.5-SDK build (Xcode 26.6) still launches and runs normally with this change (no regression).

The GitHub Actions workflow (tvOS + iOS, Debug + Release) passes on my fork: https://github.com/bartleman/moonlight-ios/actions?query=branch%3Atvos-uiscene-lifecycle

@TrueZhuangJia

Copy link
Copy Markdown

https://github.com/The-Fried-Fish/VoidLink-previously-moonlight-zwm/tree/Integration
build VoidLink TV, it's generally usable now

@bartleman
bartleman force-pushed the tvos-uiscene-lifecycle branch from 44eaf61 to d4bd55b Compare October 16, 2026 19:43
An app built against the tvOS 27 SDK that still uses the legacy
UIApplicationMain + storyboard lifecycle fails to launch: the system logs
"UIScene life cycle is required for apps built with this SDK", scene
creation fails, and the app exits before main. (Apps built against the
tvOS 26.5 SDK are exempt and still run on tvOS 27.)

Add a minimal UIApplicationSceneManifest to the tvOS Info.plist and a small
UIWindowSceneDelegate that builds the window from the Main storyboard. The
scene delegate is declared in AppDelegate.m under TARGET_OS_TV to avoid adding
a new source file to the project. Also make the HDR/refresh-rate display code
scene-safe: under the scene lifecycle the app delegate's -window is nil, so
read the window from the view controller, falling back to the connected
UIWindowScene's window if the view isn't attached yet (the stream is started
from viewDidLoad, so the HDR callback can arrive before the push completes).

Only the tvOS target is touched; the iOS target is unchanged (it will need
the same migration when built against a future iOS SDK that enforces scenes).

Tested on Apple TV 4K (tvOS 27.0) built with Xcode 27: the app launches, the
UI appears, and streaming works; the tvOS 26.5-SDK build is unaffected.

Claude-Session: https://claude.ai/code/session_01QiVtyqxowFKZc8gKnNjevy
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WKAGYAMWc88QimLyC7s3Va
@bartleman
bartleman force-pushed the tvos-uiscene-lifecycle branch from d4bd55b to 1fe2421 Compare October 16, 2026 20:03
@bartleman

Copy link
Copy Markdown
Author

Rebased onto current master (after the Xcode 27 project updates and the switch to GitHub Actions) and squashed to a single commit. The one functional change since the original revision is in updatePreferredDisplayMode:: when the view isn't attached to a window yet it now falls back to the connected UIWindowScene's window rather than the app delegate's, which is always nil under the scene lifecycle.

The CI workflow passes on my fork for both targets, Debug and Release: https://github.com/bartleman/moonlight-ios/actions/runs/38959480526

The AppVeyor failure shown on the earlier revision predates the CI switch; the workflow run here just needs approval to run.

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.

2 participants