rotorgames / Rg.Plugins.Popup

Xamarin Forms popup plugin
MIT License
1.15k stars 337 forks source link

NullReferenceException after "KeyboardDownNotification" #736

Open wtheronjones opened 2 years ago

wtheronjones commented 2 years ago

My app uses Rg.Plugins.Popup, and we are seeing a lot of notifications from our app crash logs (15 times in last 30 days) regarding a NullReferenceException.

The stack trace is as follows:

System.NullReferenceException: Object reference not set to an instance of an object
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.ViewDidLayoutSubviews () <0x10863ad40 + 0x002f4> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.OnKeyboardAnimated () <0x10863b450 + 0x00027> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at ObjCRuntime.Trampolines+SDAction.Invoke (System.IntPtr block) <0x10583d0a0 + 0x0005b> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper native-to-managed) ObjCRuntime.Trampolines+SDAction.Invoke(intptr)
  at (wrapper managed-to-native) ObjCRuntime.Messaging.objc_msgSend(intptr,intptr,double,intptr,intptr)
  at UIKit.UIView.AnimateNotify (System.Double duration, System.Action animation, UIKit.UICompletionHandler completion) <0x105808b60 + 0x00147> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at UIKit.UIView.AnimateNotifyAsync (System.Double duration, System.Action animation) <0x105808ce0 + 0x00157> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at UIKit.UIView.AnimateAsync (System.Double duration, System.Action animation) <0x105808490 + 0x0001b> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.KeyBoardDownNotification (Foundation.NSNotification notifi) <0x10863b490 + 0x00303> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper managed-to-native) ObjCRuntime.Messaging.objc_msgSend(intptr,intptr,double,intptr,intptr)
  at UIKit.UIView.AnimateNotify (System.Double duration, System.Action animation, UIKit.UICompletionHandler completion) <0x105808b60 + 0x00147> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at UIKit.UIView.AnimateNotifyAsync (System.Double duration, System.Action animation) <0x105808ce0 + 0x00157> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at UIKit.UIView.AnimateAsync (System.Double duration, System.Action animation) <0x105808490 + 0x0001b> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.KeyBoardDownNotification (Foundation.NSNotification notifi) <0x10863b490 + 0x00303> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) <0x104646040 + 0x00053> in <25bf495f7d6b4944aa395b3ab5293479#859d30dd13acd45c35a25b479c3dc625>:0
  at Foundation.NSAsyncSynchronizationContextDispatcher.Apply () <0x1057b5f60 + 0x0002b> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) <0x1057e90c0 + 0x0005f> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Offline.iOS.Application.Main (System.String[] args) <0x1043de0c0 + 0x002f3> in <7ea7e499aa694ea9bdf6b2fd9db66724#859d30dd13acd45c35a25b479c3dc625>:0

This particular stack trace captured from an Model: iPhone14,3 w/ iOS 15.4.1 on it

I'm unsure of reproduction steps, but it continues to happen. Seems to be related to the keyboard being dismissed based on the stack trace.

I've looked at PopupPageRenderer.ViewDidLayoutSubviews() and I'm wondering about possible null values:

Can UIScreen.MainScreen be null ? Can UIApplication.SharedApplication.KeyWindow be null?

LuckyDucko commented 2 years ago

@wtheronjones the area concerning that can be a bit dicey, perhaps it is when the popup is closed, and then the keyboarddownnotification occurs?

Having a project to work on would be the most helpful in trying to track this down however

wtheronjones commented 2 years ago

Hi, yeah it seems a bit dicey indeed. Unfortunately, I have no clue about the exact user interactions sequence involved, and I have lots of variations on this stack trace, not all of them include the keyboardboard down thing, but they all reference "PopupPageRenderer.ViewDidLayoutSubviews()". It's not really possible to provide a sample reproducing it.

Here is the most recent stack trace from an iPad on iOS 15.3:

The unhandled Exception was: System.NullReferenceException: Object reference not set to an instance of an object
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.ViewDidLayoutSubviews () <0x104b16d40 + 0x002f4> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) <0x101cc50c0 + 0x0005f> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Offline.iOS.Application.Main (System.String[] args) <0x1008ba0c0 + 0x002f3> in <7ea7e499aa694ea9bdf6b2fd9db66724#859d30dd13acd45c35a25b479c3dc625>:0

Here is the code in ViewDidLayoutSubviews. I am wondering what could possibly be null in there.

        public override void ViewDidLayoutSubviews()
        {
            base.ViewDidLayoutSubviews();

            var currentElement = CurrentElement;

            if (View?.Superview?.Frame == null || currentElement == null)
                return;

            var superviewFrame = View.Superview.Frame;
            var applactionFrame = UIScreen.MainScreen.ApplicationFrame;

            Thickness systemPadding;

            if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
            {
                var safeAreaInsets = UIApplication.SharedApplication.KeyWindow.SafeAreaInsets;

                systemPadding = new Thickness(
                    safeAreaInsets.Left,
                    safeAreaInsets.Top,
                    safeAreaInsets.Right,
                    safeAreaInsets.Bottom);
            }
            else
            {
                systemPadding = new Thickness
                {
                    Left = applactionFrame.Left,
                    Top = applactionFrame.Top,
                    Right = applactionFrame.Right - applactionFrame.Width - applactionFrame.Left,
                    Bottom = applactionFrame.Bottom - applactionFrame.Height - applactionFrame.Top
                };
            }

            currentElement.SetValue(PopupPage.SystemPaddingProperty, systemPadding);
            currentElement.SetValue(PopupPage.KeyboardOffsetProperty, _keyboardBounds.Height);

            if (Element != null)
                SetElementSize(new Size(superviewFrame.Width, superviewFrame.Height));

            currentElement.ForceLayout();
        }
wtheronjones commented 2 years ago

Here's another stacktrace w/ the same exception:

The unhandled Exception was: System.NullReferenceException: Object reference not set to an instance of an object
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.ViewDidLayoutSubviews () <0x108472d40 + 0x002f4> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper managed-to-native) ObjCRuntime.Messaging.objc_msgSend(intptr,intptr)
  at CoreAnimation.CALayer.LayoutSublayers () <0x10561a250 + 0x00043> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker+<>c__DisplayClass32_0.<OnUpdateNativeControl>g__update|0 () <0x105883490 + 0x004d7> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker.OnUpdateNativeControl (CoreAnimation.CALayer caLayer) <0x105882470 + 0x00813> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker.UpdateNativeControl () <0x105882dc0 + 0x0013b> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker.HandleRedrawNeeded (System.Object sender, System.EventArgs e) <0x1058823c0 + 0x0001b> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.VisualElement.BatchCommit () <0x1048d0b90 + 0x000c3> in <c28c133755b141359a285d7a0b4a28c9#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) <0x1048cecf0 + 0x000df> in <c28c133755b141359a285d7a0b4a28c9#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) <0x1048d1a10 + 0x00033> in <c28c133755b141359a285d7a0b4a28c9#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.PageRenderer.SetElementSize (Xamarin.Forms.Size size) <0x1058bcbc0 + 0x000af> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.Platform.AddChild (Xamarin.Forms.VisualElement view) <0x1058766b0 + 0x0038b> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.Platform.WillAppear () <0x105876590 + 0x0008b> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at Xamarin.Forms.Platform.iOS.PlatformRenderer.ViewWillAppear (System.Boolean animated) <0x10587aeb0 + 0x00057> in <7cbae75e123c467eb27876e5c72d7719#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) <0x1056210c0 + 0x0005f> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Offline.iOS.Application.Main (System.String[] args) <0x1042160c0 + 0x002f3> in <7ea7e499aa694ea9bdf6b2fd9db66724#859d30dd13acd45c35a25b479c3dc625>:0
wtheronjones commented 2 years ago

Here's another stack trace:

The unhandled Exception was: System.NullReferenceException: Object reference not set to an instance of an object
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.ViewDidLayoutSubviews () <0x1046ef720 + 0x002f4> in <8f5d2fad66dc4ed5ad1b62d29663d31f#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at (wrapper managed-to-native) ObjCRuntime.Messaging.objc_msgSend(intptr,intptr)
  at CoreAnimation.CALayer.LayoutSublayers () <0x101890c90 + 0x00043> in <7a25fbab2bab4f9fb861eff5e989f7ae#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker+<>c__DisplayClass32_0.<OnUpdateNativeControl>g__update|0 () <0x101afdd90 + 0x004d7> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker.OnUpdateNativeControl (CoreAnimation.CALayer caLayer) <0x101afcd70 + 0x00813> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker.UpdateNativeControl () <0x101afd6c0 + 0x0013b> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.VisualElementTracker.HandleRedrawNeeded (System.Object sender, System.EventArgs e) <0x101afccc0 + 0x0001b> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.VisualElement.BatchCommit () <0x100b44c10 + 0x000c3> in <c28c133755b141359a285d7a0b4a28c9#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.VisualElement.set_Bounds (Xamarin.Forms.Rectangle value) <0x100b42d70 + 0x000df> in <c28c133755b141359a285d7a0b4a28c9#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.VisualElement.Layout (Xamarin.Forms.Rectangle bounds) <0x100b45a90 + 0x00033> in <c28c133755b141359a285d7a0b4a28c9#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.PageRenderer.SetElementSize (Xamarin.Forms.Size size) <0x101b374c0 + 0x000af> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.Platform.AddChild (Xamarin.Forms.VisualElement view) <0x101af0fb0 + 0x0038b> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.Platform.WillAppear () <0x101af0e90 + 0x0008b> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at Xamarin.Forms.Platform.iOS.PlatformRenderer.ViewWillAppear (System.Boolean animated) <0x101af57b0 + 0x00057> in <7cbae75e123c467eb27876e5c72d7719#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) <0x101897e20 + 0x0005f> in <7a25fbab2bab4f9fb861eff5e989f7ae#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
  at My.Application.Main (System.String[] args) <0x100479e00 + 0x002f3> in <d3578149affd4c11a9424688e709f8de#7d03bd2da1a2b920054b8ecc2cc9d5dc>:0
LuckyDucko commented 2 years ago

I was just looking at this area in the Maui Version, i might be able to adjust somethings, gimme a bit

LuckyDucko commented 2 years ago

Hmm, i wonder if it is this

var applactionFrame = UIScreen.MainScreen.ApplicationFrame;

I am definitely going to need a project to work off, however, is there some lifecycle events that may cause a situation where an app is brought to the foreground, and almost immediately it opens a popup? just spit balling

wtheronjones commented 2 years ago

I was wondering about that line too. I can't imagine why it's null. non-ui thread?

I couldn't tell you about the user behaviors leading up to it, I just get random error reports containing versions of this stack trace. I can tell you, the errors are always from iOS devices.
I can't provide a project that recreates it, but I can describe a bit of what's going on in our project.

In our project, all the Xamarin.Forms pages are using "" as the root xaml item. We aren't really using any popup features. I will note that UWP handles page resizing nicely because we inherit the behavior from this class. Also, the app isn't a 100% Xamarin.Forms app. We're using native view controllers and using the Xamarin.Forms.PageExtensions.CreateViewController() method to insert the XF page into the view as native, like this:

 var viewModel = CreateMyViewModel();
 var myPage = new MyPopupDerivedPage
  {
      BindingContext = _viewModel
  };
  var myVC = myPage.CreateViewController();
  AddChildViewController(myVC);
  View.Add(myVC.View);
  myVC.DidMoveToParentViewController(this);
}

Got another one today:

The unhandled Exception was: System.NullReferenceException: Object reference not set to an instance of an object
  at Rg.Plugins.Popup.IOS.Renderers.PopupPageRenderer.ViewDidLayoutSubviews () <0x108e7ad40 + 0x002f4> in <8951cf88b24144fc8b14be29eb0678ad#859d30dd13acd45c35a25b479c3dc625>:0
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) <0x1060290c0 + 0x0005f> in <7a25fbab2bab4f9fb861eff5e989f7ae#859d30dd13acd45c35a25b479c3dc625>:0
  at Offline.iOS.Application.Main (System.String[] args) <0x104c1e0c0 + 0x002f3> in <7ea7e499aa694ea9bdf6b2fd9db66724#859d30dd13acd45c35a25b479c3dc625>:0