Forum Xamarin.Forms

Share from Xamarin Essentials mysteriously quit working after updates, but only on iPad on iOS13.2

I updated my iPad to 13.2, updated to latest XCode on my mac, updated VS, updated to XF 4.3.

I know, not smart.

Everything appeared to work, until I tried the SHARE function of my app on iPad. The pop-over does not appear. An older version of my app works OK, and the new version works OK on my iPhone running 13.1.3.

I did try rolling back XF to what I was using (since it was easy), no help there.

Oh, and well there's another part to this mystery. To share multiple files, I wrote my own code using the iOS api, including creating an Activity Vew Controller (the pop-over). This doesn't work either.

Is there some kind of iPad settings or Info.plist thing I'm missing here? Got me very confused.

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    How did you present the Activity Vew Controller using native code?
    I tested like:

    partial void BtnClick(UIKit.UIButton sender)
    {
        UIActivityViewController activityVC = new UIActivityViewController(new NSObject[] { new NSString("String To Share") }, null);
    
        if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad)
        {
            activityVC.PopoverPresentationController.SourceView = sender;
        }
    
        PresentViewController(activityVC, true, null);
    }
    

    It works fine on iPad with iOS 13.2.

  • BobWhittenBobWhitten USMember ✭✭

    Thanks @LandLu.

    I'm asking for a bit more than that for the native code: subject & message, in case user emails (which would be typical for myt application.

            static private async void ShareFileAsync( string filePath, string msgSubject, string msgBody) {
                try {
                    var items = new NSObject[] { NSObject.FromObject(msgBody), NSUrl.FromFilename(filePath) };
    
                    var activityController = new UIActivityViewController(items, null);
                    activityController.SetValueForKey(NSObject.FromObject(msgSubject), (NSString)"Subject");
                    var rootController = UIApplication.SharedApplication.KeyWindow.RootViewController;
                    while (rootController.PresentedViewController != null) {
                        rootController = rootController.PresentedViewController;
                    }
    
                    NSString[] excludedActivityTypes = null;
                    excludedActivityTypes = new NSString[] { UIActivityType.AssignToContact, UIActivityType.AddToReadingList, UIActivityType.CopyToPasteboard, UIActivityType.SaveToCameraRoll };
    
                    if (excludedActivityTypes != null && excludedActivityTypes.Length > 0)
                        activityController.ExcludedActivityTypes = excludedActivityTypes;
    
                    if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad) {
                        activityController.PopoverPresentationController.SourceView = rootController.View;
                    }
    
                    await rootController.PresentViewControllerAsync(activityController, true);
                } catch (Exception ex) {
                    logp( $"ShareFileAsync() Exception ex={ex}");   // not being hit
                }
            }
    

    So, I do have the iPad check, as you do. I checked the Xamarin code for text sharing, and it doesn't seem to have this. But up until now it has been working for me.

    I also found a while back I needed the while() that gets "right" root controller view to work as my source view. I see your code uses a convenient view (the button) as source view. I'm wondering now if this is related to my issue.

  • BobWhittenBobWhitten USMember ✭✭

    Update: Tried this on several different iPads ( iPad Mini 2 with 12.4.2, iPad Air 2 with 10.3.2, and iPad Air 2 with 13.2).
    The failure to pop-up "share" pop up only seems to happen on iPad Air 2 with 13.2.

  • BobWhittenBobWhitten USMember ✭✭

    Update2: iPad Air 2 with 12.4.1 -- also works fine.
    iPhone with 13.2 -- also works.
    This still leaves iPad with 13.2 as the only failing configuration I have.

  • LandLuLandLu Member, Xamarin Team Xamurai
    edited November 2019

    I see your code uses a convenient view (the button) as source view. I'm wondering now if this is related to my issue.

    Yes, I think it could be.
    When you set the SourceView to the whole view you also need to configure SourceRect the like:

    activityController.PopoverPresentationController.SourceRect = new CGRect(0, 100, 100, 100);
    

    If the SourceRect hasn't been set the activity view can't be shown on iPads Air either on my side.
    However, it could still be related to the approach which you used to obtain the topController. I think the entire code should be like:

    UIViewController topViewControllerWithRootViewController(UIViewController rootViewController)
    {
        if (rootViewController is UITabBarController) 
        {
            UITabBarController tabBarController = (UITabBarController)rootViewController;
            return topViewControllerWithRootViewController(tabBarController.SelectedViewController);
        } 
        else if (rootViewController is UINavigationController) 
        {
            UINavigationController navigationController = (UINavigationController)rootViewController;
            return topViewControllerWithRootViewController(navigationController.VisibleViewController);
        } 
        else if (rootViewController.PresentedViewController != null) 
        {
            UIViewController presentedViewController = rootViewController.PresentedViewController;
            return topViewControllerWithRootViewController(presentedViewController);
        } 
        else 
        {
            return rootViewController;
        }
    }
    

    And consume it like:

    var keyWindow = UIApplication.SharedApplication.Windows.FirstOrDefault(x => x.IsKeyWindow == true);
    var topViewController = topViewControllerWithRootViewController(keyWindow.RootViewController);
    
  • BobWhittenBobWhitten USMember ✭✭

    @LandLu -- I did find that setting SourceRect "fixed" my native code issue. THANK YOU.

    Looking at the topViewControllerWithRootViewController() part of the solution -- it sure appears that this is more thorough than my "while" fix, so I've incorporated that too.

    BUT, the Xamarin Essentials "share" text still does not work... ANYONE?

  • LandLuLandLu Member, Xamarin Team Xamurai

    Maybe, this is also caused by the SourceRect. If you didn't explicitly set the position the activity view will display at the left top corner on iOS 13.2. I've seen you posted an issue here:
    https://github.com/xamarin/Essentials/issues/979
    And you could use my approach to separately implement it on iOS.

  • BobWhittenBobWhitten USMember ✭✭

    I posted issue 979. I'm thinking of posting a PR for this.

  • dsanchodsancho USMember ✭✭

    I'm having the same problem. Using Xamarin Essentials 1.52 on an iPad with ios 13.3.1, nothing it's shared unless I call twice to RequestAsync.

  • jchavesCRjchavesCR Member

    @dsancho said:
    I'm having the same problem. Using Xamarin Essentials 1.52 on an iPad with ios 13.3.1, nothing it's shared unless I call twice to RequestAsync.

    You need to pass the parameter PresentationSourceBounds for Tablet Devices in IOS, similar to this code to work fine.
    Share.RequestAsync(new ShareFileRequest
    {
    Title = "",
    File = new ShareFile(file), PresentationSourceBounds = DeviceInfo.Platform == DevicePlatform.iOS && DeviceInfo.Idiom == DeviceIdiom.Tablet
    ? new System.Drawing.Rectangle(300, 300, 0, 0)
    : System.Drawing.Rectangle.Empty
    });

Sign In or Register to comment.