Skip to content

v0.1.3 — Skip invisible first-VC animation on off-screen nav

Choose a tag to compare

@Sajjon Sajjon released this 04 May 08:14
· 40 commits to main since this release
9cda1ec

Patch release with a narrow perf optimization for coordinator startup.

What was happening

When a coordinator started up by seating its first scene into a brand-new `UINavigationController` that was about to be modally presented, the code in `UINavigationController.setRootViewControllerIfEmptyElsePush(viewController:animated:…)` called `setViewControllers([vc], animated: true)`. UIKit then ran a ~0.35s push-style animation on the off-screen nav controller. The user never saw that animation — they only ever saw the modal-present animation that fired afterward — but the visible modal-present animation was effectively gated behind the invisible inner one finishing first. End result: a perceptible delay between "tap CTA" and "modal appears" with no user-visible work happening during it.

The fix

When the nav controller is both empty AND off-screen (`viewIfLoaded?.window == nil`), force `animated: false` on the empty-stack branch. The user can't see the animation anyway; the visible modal-present animation chain is no longer gated on it.

`didAnimate` is tracked through the branches so the completion-routing logic uses the correct path (transition-coordinator callback for animated transitions; `DispatchQueue.main.async` next-tick for non-animated ones).

What stays the same

  • On-screen empty stacks (e.g., a visible nav whose stack was just cleared by a `.replace` transition and is about to receive its first VC): the caller's `animated` flag is honored. The first insertion is the user-visible transition and must continue to animate when requested.
  • `forceReplaceAllVCsInsteadOfPush` semantics: unchanged for on-screen navs. The flag only diverged from `animated` in the previous (buggy) revision when the stack was empty regardless of visibility.
  • Non-empty stacks: untouched. `pushViewController(_:animated:)` runs as before.

Migration from 0.1.2

Trivial. Bump the pin:

```swift
.package(url: "https://github.com/Sajjon/NanoViewController.git", exact: "0.1.3")
```

Full changelog: v0.1.2...v0.1.3