xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] Navigation stack of NavigationPage corrupted after PopAsync with modal page visible on iOS #14551

Open cpraehaus opened 3 years ago

cpraehaus commented 3 years ago

Description

We are using NavigationPage to show our MainPage as root page. At some point in our application we want to switch from a non-modal page (Page1) - that was pushed on the nav. stack - to a modal page (Page2), so that when the user navigates back (closes the modal page) he comes back to the main page (and not to Page1).

But this sequence of nav. operations described in repro below causes the navigation stack to get corrupted on iOS, producing different kinds of follow-up errors. On Android everything works perfectly.

The problem is that the implementation of PopAsync on iOS removes the Page from the visual stack and waits for page visibility events (disappearing) which it does not get immediately since the modal stack is active showing Page2 and hiding Page1.

Now PopAsync(Page1) waits for page disappearing event (unfortunately using a very poor implementation which waits for multiple event types and so also receives appearing event).

26320525-ca75-414a-af91-711f0f1cde82

When modal page (Page2) is removed/closed an appearing event followed by a disappearing event is generated for (non-modal) page Page1. Thereby the first PopAsync is unblocked but sees that it received appearing event and not disappearing as it would have expected (see iOS.NavigationRenderer.OnPopViewAsync) . So it considers the removal failed (sets actuallyRemoved to false) and PopAsync will then not remove Page1 from nav stack. But actually the page IS REMOVED and not visible anymore, so the nav stack is corrupted and following nav actions will certainly fail at some point.

Steps to Reproduce

  1. Push non-modal Page1 on nav stack using PushAsync
  2. Push modal page Page2 on modal stack using PushModalAsync
  3. Pop Page1 from nav stack while modal Page2 is visible using PopAsync
  4. Close modal page Page2 using PopModalAsync
  5. PopAsync removed page from visual stack but does not remove it form nav stack, resulting in corrupted nav stack.
  6. Due to corrupted nav stack further NavigationPage operations will eventually fail

Expected Behavior

Page1 is removed from visual stack and from (non-modal) navigation stack Navigation.NavigationStack leaving nav. stack in consistent state.

Actual Behavior

Page1 is removed from visual stack but not from (non-modal) navigation stack Navigation.NavigationStack leaving nav. stack in inconsistent state.

Basic Information

Environment

Not relevant.

Build Logs

Not relevant.

Screenshots

Not relevant.

Reproduction Link

Sandbox_NavStackCorruptAfterPop.zip

Run Xamarin.Forms.Sandbox.iOS. Click the buttons until you receive the error dialog.

Workaround

No workaround.

arda-a commented 1 year ago

I have exactly the same issue. Have you been able to find a workaround for this ?

cpraehaus commented 1 year ago

@arda-a No, we don't have a work-around. In our case (we have a navigation service wrapping the NavigationPage) we ended up avoiding the that the situation arises by deferring the PopAsync until the modal stack is empty again.

arda-a commented 1 year ago

Thanks very much for the response. I ended up doing the same.