Skip to content

[iOS] Can navigate to another page on iOS 26+ #32374

@raselldev

Description

@raselldev

Description

I have LoginPage, when user click LOGIN, the app must be change to AppShell.
But the UI stuck on LoginPage.

this my code for go to AppShell

`private async Task GoToAppShellAndSync()
{
System.Diagnostics.Debug.WriteLine("[LOGIN] GoToAppShellAndSync called");

        var appShell = new AppShell();

        // iOS 18+ ULTIMATE FIX: Pop NavigationPage and set window.Page directly with force refresh
        await Application.Current.Dispatcher.DispatchAsync(async () =>
        {
            System.Diagnostics.Debug.WriteLine("[LOGIN] Starting navigation on dispatcher");
            
            if (Application.Current?.Windows != null && Application.Current.Windows.Count > 0)
            {
                var window = Application.Current.Windows[0];
                System.Diagnostics.Debug.WriteLine($"[LOGIN] Current window.Page type: {window.Page?.GetType().Name}");
                
                // If wrapped in NavigationPage, pop all pages first
                if (window.Page is NavigationPage navPage)
                {
                    System.Diagnostics.Debug.WriteLine($"[LOGIN] NavigationPage detected, stack count: {navPage.Navigation.NavigationStack.Count}");
                    
                    // Pop all pages to clear the navigation stack
                    while (navPage.Navigation.NavigationStack.Count > 0)
                    {
                        await navPage.Navigation.PopAsync(false);
                    }
                    
                    System.Diagnostics.Debug.WriteLine("[LOGIN] Navigation stack cleared");
                }
                
                // Now set window.Page directly to AppShell
                System.Diagnostics.Debug.WriteLine("[LOGIN] Setting window.Page to AppShell");
                window.Page = appShell;
                
                // Force iOS to recognize the change
                #if IOS
                if (window.Handler?.PlatformView is UIKit.UIWindow uiWindow)
                {
                    System.Diagnostics.Debug.WriteLine("[LOGIN] Forcing iOS UIWindow to refresh");
                    uiWindow.RootViewController = appShell.Handler?.PlatformView as UIKit.UIViewController;
                    uiWindow.MakeKeyAndVisible();
                }
                #endif
                
                System.Diagnostics.Debug.WriteLine("[LOGIN] Window.Page set to AppShell");
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("[LOGIN] WARNING: No windows available!");
                Application.Current.MainPage = appShell;
            }
        });

        // Wait for iOS to process
        await Task.Delay(500);
        System.Diagnostics.Debug.WriteLine("[LOGIN] Post-navigation delay completed");

        // Then sync data in background WITHOUT awaiting
        Task.Run(async () =>
        {
            LoadingPopup? loadingPopup = null;

            try
            {
                // Small delay to ensure Shell is fully loaded
                await Task.Delay(500);

                // Show loading popup on UI thread
                await Application.Current.Dispatcher.DispatchAsync(() =>
                {
                    if (Shell.Current?.CurrentPage != null)
                    {
                        loadingPopup = new LoadingPopup("Sinkronisasi data...\nMohon tunggu sebentar");
                        Shell.Current.CurrentPage.ShowPopup(loadingPopup);
                    }
                });

                MasterDataService masterDataService = new MasterDataService();
                await masterDataService.SyncData(true);

                System.Diagnostics.Debug.WriteLine("[LOGIN] Background sync completed successfully");

                // Hide loading popup on UI thread
                await Application.Current.Dispatcher.DispatchAsync(() => { loadingPopup?.Close(); });

                // REMOVED: Success alert dialog that was causing the loop
                // Just log success instead
                System.Diagnostics.Debug.WriteLine("[LOGIN] Sinkronisasi data selesai");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[ERROR] Background sync failed: {ex.Message}");
                System.Diagnostics.Debug.WriteLine($"[ERROR] StackTrace: {ex.StackTrace}");

                // Hide loading popup on error
                await Application.Current.Dispatcher.DispatchAsync(() => { loadingPopup?.Close(); });

                // Show error message
                await Application.Current.Dispatcher.DispatchAsync(async () =>
                {
                    if (Shell.Current?.CurrentPage != null)
                    {
                        await Shell.Current.CurrentPage.DisplayAlert(
                            "Error",
                            $"Gagal sinkronisasi data: {ex.Message}",
                            "OK");
                    }
                });
            }
        });
    }`

Steps to Reproduce

  1. Login
  2. Click Button LOGIN
  3. Stuck on LoginPage => expected result must be go to AppShell

Link to public reproduction project repository

No response

Version with bug

9.0.111 SR11.1

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

9.0.10 SR1

Affected platforms

iOS

Affected platform versions

iOS 26+

Did you find any workaround?

No response

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions