Search code examples
xamarin.iosxamarin.formsshareuitapgesturerecognizer

Xamarin.Forms Warning: Attempt to present * on * whose view is not in the window hierarchy with iOS image/gesture recogniser


I have a modal Navigation page with an image which acts like a button;

<Image Source ="share.png" HeightRequest="32" WidthRequest="32">
    <Image.GestureRecognizers>
        <TapGestureRecognizer Tapped="On_Share" />
    </Image.GestureRecognizers>
</Image>

And the method behind;

async void On_Share(object sender, EventArgs e)
{
    if (CrossConnectivity.Current.IsConnected)
    {
        var message = "Share this";
        var title = "Share";
        await CrossShare.Current.Share(new ShareMessage { Text = message, Title = title}, new ShareOptions { ExcludedUIActivityTypes = new[] { ShareUIActivityType.PostToFacebook } });
    }
    else
    {
        NoInternetLabel.IsVisible = true;
    }
 }

I'm getting the error when I try to click on the share image/button. I've put breakpoints into the first line of the On_Share method & they're not being hit.

Warning: Attempt to present <UIActivityViewController: 0x141b60f70> on <Xamarin_Forms_Platform_iOS_ModalWrapper: 0x1419a0920> whose view is not in the window hierarchy!

Please note this works fine in Android, I'm only seeing issues in iOS. I'm not sure what is going on - I'm not trying to present any other windows or anything when I click the image. Regardless, the error appears before the process reaches the beginning of the On_Share method. What am I missing here?

EDIT: The method does get hit now, and I'm still getting the error. It must be trying to send up the share sheet and failing...


Solution

  • There was a problem with the Share plugin in the end - we resolved it by making part of the code recursive.

    the GetVisibleViewController used to look like this;

    UIViewController GetVisibleViewController()
    {
        var rootController = UIApplication.SharedApplication.KeyWindow.RootViewController;
    
        if (rootController.PresentedViewController == null)
            return rootController;
    
        if (rootController.PresentedViewController is UINavigationController)
        {
            return ((UINavigationController)rootController.PresentedViewController).VisibleViewController;
        }
    
        if (rootController.PresentedViewController is UITabBarController)
        {
            return ((UITabBarController)rootController.PresentedViewController).SelectedViewController;
        }
    
        return rootController.PresentedViewController;
    }
    

    whereas it needed to cycle through to find the top UIViewController;

    UIViewController GetVisibleViewController(UIViewController controller = null)
    {
        controller = controller ?? UIApplication.SharedApplication.KeyWindow.RootViewController;
    
        if (controller.PresentedViewController == null)
            return controller;
    
        if (controller.PresentedViewController is UINavigationController)
        {
            return ((UINavigationController)controller.PresentedViewController).VisibleViewController;
        }
    
        if (controller.PresentedViewController is UITabBarController)
        {
            return ((UITabBarController)controller.PresentedViewController).SelectedViewController;
        }
    
        return GetVisibleViewController(controller.PresentedViewController);
    }
    

    I've raised the issue and submitted a pull request on the github