Skip to content

[BugFix][iOS] Avoid host orientation recursion - #129

Open
Huxpro wants to merge 1 commit into
tiktok:agent/ios-fixed-lynx-viewportfrom
Huxpro:agent/ios-orientation-host-fallback
Open

[BugFix][iOS] Avoid host orientation recursion#129
Huxpro wants to merge 1 commit into
tiktok:agent/ios-fixed-lynx-viewportfrom
Huxpro:agent/ios-orientation-host-fallback

Conversation

@Huxpro

@Huxpro Huxpro commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • use the navigation stack's actual top controller as the orientation source
  • avoid recursively asking UINavigationController for the same delegate-owned policy
  • preserve typed Sparkling orientation when the top controller is an SPKViewController

Regression

A Sparkling-owned navigation stack can later present a non-Sparkling tooling controller. The previous fallback called navigationController.supportedInterfaceOrientations from the navigation delegate itself, recursively re-entering the same callback until the main-thread stack overflowed.

Validation

  • SparklingGoTests: 337 tests in 20 suites passed on iOS Simulator
  • new coverage uses a non-Sparkling top controller with an explicit orientation policy

Stack

- Read orientation from the navigation stack top controller for every host type.
- Fall back to the Sparkling controller base policy when the stack has no top controller.
- Cover a non-Sparkling host controller to prevent delegate recursion.

TEST: SparklingGoTests passed 337 tests in 20 suites on iOS Simulator.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
@dirtmelon
dirtmelon requested review from LittleGru and dirtmelon and a lite review from Copilot August 11, 2026 04:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an iOS navigation-controller orientation regression in Sparkling by changing how SPKViewController (as a UINavigationControllerDelegate) derives supported/preferred interface orientations, preventing recursive delegate re-entry and main-thread stack overflow when a non-Sparkling controller is on top of a Sparkling-owned navigation stack.

Changes:

  • Update UINavigationControllerDelegate orientation callbacks to use the navigation stack’s actual topViewController orientation properties (avoiding calling back into UINavigationController).
  • Add a new router test covering the “non-Sparkling top controller” scenario.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/sparkling-sdk/ios/Sparkling/Sources/Application/Container/SPKViewController.swift Adjusts orientation delegate methods to avoid recursive fallback and use the actual top VC as the policy source.
packages/playground/ios/SparklingGoTests/Application/SPKRouterTests.swift Adds test coverage for a navigation stack where the top controller is not Sparkling-owned.
Suppressed comments (1)

packages/sparkling-sdk/ios/Sparkling/Sources/Application/Container/SPKViewController.swift:1133

  • Same issue as above for preferred orientation: falling back to super.preferredInterfaceOrientationForPresentation bypasses SPKViewController.preferredInterfaceOrientationForPresentation (which applies SPKContext.interfaceOrientationPolicy). Use self.preferredInterfaceOrientationForPresentation as the safe fallback when the navigation stack is empty.
        return navigationController.topViewController?
            .preferredInterfaceOrientationForPresentation
            ?? super.preferredInterfaceOrientationForPresentation

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +1124 to +1125
return navigationController.topViewController?.supportedInterfaceOrientations
?? super.supportedInterfaceOrientations
Comment on lines +129 to +142
let delegate = SPKViewController(
withURL: nil,
config: SPKSchemeParam(),
context: SPKContext(),
frame: .zero)
let host = HostViewController()
let navigationController = UINavigationController(rootViewController: host)

#expect(
delegate.navigationControllerSupportedInterfaceOrientations(
navigationController) == .portraitUpsideDown)
#expect(
delegate.navigationControllerPreferredInterfaceOrientationForPresentation(
navigationController) == .portraitUpsideDown)
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