private void DidShowViewController(UINavigationController navigationController, UIViewController viewController, bool animated)
        {
            TraceViewControllers(nameof(DidShowViewController), viewController);

            if (!(viewController is PageViewController pageViewController))
            {
                // When the ViewController isn't a PageViewController, it means it doesn't have anything to do with the Frame.
                // It's possibly a modal ViewController.
                // We just ignore it.
                return;
            }

            var lastRequest = pageViewController.AssociatedRequests.LastOrDefault();

            if (lastRequest != null)
            {
                // Mark the request as handled by the NavigationController.
                lastRequest.WasHandledByController = true;

                if (lastRequest == _controllerToFrameRequest)
                {
                    _frameToControllerRequests.Remove(_controllerToFrameRequest);
                    _controllerToFrameRequest = null;
                }
                else
                {
                    if (TryGetLast(_frameToControllerRequests, out var frameRequest))
                    {
                        if (NavigationRequest.Correlates(lastRequest, frameRequest))
                        {
                            // Now that the NavigationController handled the frame request, we remove it from the list.
                            _frameToControllerRequests.RemoveLast();
                        }
                        else
                        {
                            // Note for the future: We might be able to improve this by reseting the Frame to the NavigationController's content.
                            // However, this case doesn't seem to really happen.

                            // Something bad happened. We clear the request queue to try to recover.
                            _frameToControllerRequests.Clear();
                            this.Log().Error($"Can't process DidShowViewController because the last request doesn't match the current request.");
                        }
                    }
                    else
                    {
                        // It's possible that the NavigationController is the source of this event. When that's the case, the list of Frame requests is possibly empty.
                    }
                }
            }
            else
            {
                this.Log().Error($"Can't process DidShowViewController because the current PageViewController's AssociatedRequests list is empty.");
            }
        }
        /// <summary>
        /// This is called on <see cref="Frame.Navigating"/>.
        /// We use this handler to cancel the navigation when the request conflicts with the <see cref="NavigationController"/>.
        /// </summary>
        private void OnFrameNavigating(object sender, NavigatingCancelEventArgs e)
        {
            if (e.Cancel)
            {
                // If something cancelled the navigation, we simply ignore the event.
                return;
            }

            var frameRequest = new NavigationRequest(_frame, e);

            if (_controllerToFrameRequest != null)
            {
                // We get here when the UINavigationController initiated a navigation (like a back swipe) that is being executed by the Frame.
                if (NavigationRequest.Correlates(frameRequest, _controllerToFrameRequest))
                {
                    // We queue the request so that we can handle it in OnFrameNavigated and ignore it in OnFrameBackStackChanged.
                    _frameToControllerRequests.AddFirst(_controllerToFrameRequest);
                }
                else
                {
                    // When the Frame's request doesn't matche the UINavigationController's request. We cancel the Frame's request.
                    // Ex: The UINavigationController is doing a native back, but the Frame wants to go forward.
                    //     This sequencing can happen when you press back during an ViewModel operation that usually ends with a navigation.
                    e.Cancel = true;

                    if (this.Log().IsEnabled(LogLevel.Debug))
                    {
                        this.Log().Debug("Cancelled frame navigating request because a native navigation is in progress.");
                    }
                }
            }
            else
            {
                // We queue the request so that we can handle it in OnFrameNavigated and ignore it in OnFrameBackStackChanged.
                _frameToControllerRequests.AddFirst(frameRequest);
            }
        }
        /// <summary>
        /// This is called on <see cref="Frame.NavigationStopped"/>.
        /// We use this handler to remove requests cancelled by <see cref="NavigatingCancelEventArgs.Cancel"/>.
        /// </summary>
        private void OnFrameNavigationStopped(object sender, NavigationEventArgs e)
        {
            var request = new NavigationRequest(_frame, e);

            if (TryGetFirst(_frameToControllerRequests, out var frameToControllerRequest) && NavigationRequest.Correlates(request, frameToControllerRequest))
            {
                if (this.Log().IsEnabled(LogLevel.Debug))
                {
                    this.Log().Debug("Aborted navigation request because the Frame.Navigating event was cancelled.");
                }

                _frameToControllerRequests.RemoveFirst();
            }
            else
            {
                // We shouldn't get here because the frame events are synchronous.
                this.Log().Error($"Can't process OnFrameNavigationStopped because the request in queue doesn't match the current request.");
            }
        }
        /// <summary>
        /// This is called on <see cref="Frame.Navigated"/>.
        /// We use this handler to create requets for the <see cref="NavigationController"/>.
        /// </summary>
        private void OnFrameNavigated(object sender, NavigationEventArgs e)
        {
            // We create a request object from the current state. We only use this object to correlate it with existing requests.
            var request = new NavigationRequest(_frame, e);

            if (TryGetFirst(_frameToControllerRequests, out var frameRequest) && NavigationRequest.Correlates(request, frameRequest))
            {
                // Mark the request as handled by the frame because we're in the Navigated handler.
                frameRequest.WasHandledByFrame = true;

                if (frameRequest == _controllerToFrameRequest)
                {
                    // If the request is the one created by the NavigationController, we don't have to do anything at this point.
                    // The DidShowViewController method will simply remove it from the list once it gets called.
                }
                else
                {
                    // Get the page from the event args.
                    var page = e.Content as Page;

                    // Use that page to get the native ViewController.
                    var viewController = page.FindViewController() ?? new PageViewController(page);

                    // If that ViewController is a PageViewController, we add the request to its list.
                    (viewController as PageViewController)?.AssociatedRequests.Add(frameRequest);

                    // We get the isAnimated flag from the transition info.
                    var isAnimated = GetIsAnimated(frameRequest.TransitionInfo);

                    switch (frameRequest.NavigationMode)
                    {
                    case NavigationMode.Back:
                        if (this.Log().IsEnabled(LogLevel.Debug))
                        {
                            this.Log().Debug("Poping ViewController to replicate Frame's back navigation.");
                        }
                        NavigationController.PopViewController(isAnimated);
                        break;

                    case NavigationMode.Forward:
                    case NavigationMode.New:
                        if (this.Log().IsEnabled(LogLevel.Debug))
                        {
                            this.Log().Debug($"Pushing ViewController ({page.GetType().Name}) to replicate Frame's forward navigation.");
                        }
                        NavigationController.PushViewController(viewController, isAnimated);
                        break;

                    case NavigationMode.Refresh:
                    default:
                        // Refresh currently doesn't have an effect.
                        break;
                    }
                }
            }
            else
            {
                // We shouldn't get here because the frame events are synchronous.
                if (frameRequest == null)
                {
                    this.Log().Error($"Can't process OnFrameNavigated because the request queue is empty.");
                }
                else
                {
                    this.Log().Error($"Can't process OnFrameNavigated because the request in queue doesn't match the current request.");
                }
            }
        }