From 3b803c9f3d1aeb2068f3969b914456d6c74c5c76 Mon Sep 17 00:00:00 2001 From: Owen Carey <37121709+owenthcarey@users.noreply.github.com> Date: Thu, 21 May 2026 15:02:46 -0700 Subject: [PATCH 1/2] fix(ios): improve TabView handling around more navigation controller --- packages/core/ui/tab-view/index.ios.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/core/ui/tab-view/index.ios.ts b/packages/core/ui/tab-view/index.ios.ts index c2bcd9cfca..db8189b71e 100644 --- a/packages/core/ui/tab-view/index.ios.ts +++ b/packages/core/ui/tab-view/index.ios.ts @@ -134,6 +134,14 @@ class UITabBarControllerDelegateImpl extends NSObject implements UITabBarControl const owner = this._owner?.deref(); if (owner) { + // iOS lazily initializes moreNavigationController (e.g. on first access of + // topViewController, or on first tap of the More tab) and can clear the + // delegate we set in setViewControllers. Re-assert it whenever any tab is + // selected so moreNav push/pop callbacks for tabs >= 5 still reach us. + const moreNav = tabBarController.moreNavigationController; + if (moreNav && moreNav.delegate !== owner.moreNavigationControllerDelegate) { + moreNav.delegate = owner.moreNavigationControllerDelegate; + } owner._onViewControllerShown(tabBarController, viewController); } } @@ -175,6 +183,12 @@ class UINavigationControllerDelegateImpl extends NSObject implements UINavigatio const owner = this._owner?.deref(); if (owner) { owner._onViewControllerShown(navigationController.tabBarController, viewController); + + // The cascade above may have just attached a queued Page to a Frame whose + // Frame.onLoaded only fired post-animation. iOS won't re-layout on its own + // after the push completes — trigger one so the late attachment becomes visible. + viewController?.view?.setNeedsLayout(); + viewController?.view?.layoutIfNeeded(); } } } @@ -303,9 +317,8 @@ export class TabViewItem extends TabViewItemBase { export class TabView extends TabViewBase { public viewController: UITabBarControllerImpl; public items: TabViewItem[]; - + public moreNavigationControllerDelegate: UINavigationControllerDelegateImpl; private _delegate: UITabBarControllerDelegateImpl; - private _moreNavigationControllerDelegate: UINavigationControllerDelegateImpl; private _iconsCache = {}; private _bottomAccessoryNsView: View; private _ios: UITabBarControllerImpl; @@ -327,12 +340,12 @@ export class TabView extends TabViewBase { initNativeView() { super.initNativeView(); this._delegate = UITabBarControllerDelegateImpl.initWithOwner(new WeakRef(this)); - this._moreNavigationControllerDelegate = UINavigationControllerDelegateImpl.initWithOwner(new WeakRef(this)); + this.moreNavigationControllerDelegate = UINavigationControllerDelegateImpl.initWithOwner(new WeakRef(this)); } disposeNativeView() { this._delegate = null; - this._moreNavigationControllerDelegate = null; + this.moreNavigationControllerDelegate = null; this.viewController = null; this._ios = null; super.disposeNativeView(); @@ -590,7 +603,7 @@ export class TabView extends TabViewBase { } // When we set this._ios.viewControllers, someone is clearing the moreNavigationController.delegate, so we have to reassign it each time here. - this._ios.moreNavigationController.delegate = this._moreNavigationControllerDelegate; + this._ios.moreNavigationController.delegate = this.moreNavigationControllerDelegate; } private _getIconRenderingMode(): UIImageRenderingMode { From 5be34661541665df7baae5a335d0d715cf6e0433 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Thu, 21 May 2026 15:29:22 -0700 Subject: [PATCH 2/2] chore: nit Co-authored-by: Nathan Walker --- packages/core/ui/tab-view/index.ios.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/core/ui/tab-view/index.ios.ts b/packages/core/ui/tab-view/index.ios.ts index db8189b71e..e301dc8ea8 100644 --- a/packages/core/ui/tab-view/index.ios.ts +++ b/packages/core/ui/tab-view/index.ios.ts @@ -139,7 +139,7 @@ class UITabBarControllerDelegateImpl extends NSObject implements UITabBarControl // delegate we set in setViewControllers. Re-assert it whenever any tab is // selected so moreNav push/pop callbacks for tabs >= 5 still reach us. const moreNav = tabBarController.moreNavigationController; - if (moreNav && moreNav.delegate !== owner.moreNavigationControllerDelegate) { + if (moreNav && owner.moreNavigationControllerDelegate && moreNav.delegate !== owner.moreNavigationControllerDelegate) { moreNav.delegate = owner.moreNavigationControllerDelegate; } owner._onViewControllerShown(tabBarController, viewController); @@ -603,7 +603,9 @@ export class TabView extends TabViewBase { } // When we set this._ios.viewControllers, someone is clearing the moreNavigationController.delegate, so we have to reassign it each time here. - this._ios.moreNavigationController.delegate = this.moreNavigationControllerDelegate; + if (this._ios.moreNavigationController) { + this._ios.moreNavigationController.delegate = this.moreNavigationControllerDelegate; + } } private _getIconRenderingMode(): UIImageRenderingMode {